Here's a simple function that convert a string to currency format.
fun String.toCurrency(): String{
return try {
DecimalFormat("###,###").format(this.replace(",","").toInt())
} catch (E: NumberFormatException) {
this
}
}
And I want to test this method. So, I did
#Test(expected = NumberFormatException::class)
#Throws(NumberFormatException::class)
fun convertCurrency_returnAmericanFormat() {
val currentList = listOf("0", "1", "10", "100", "1000", "10000", "100000", "1000000", "100000000")
val expectedList = listOf("0", "1", "10", "100", "1,000", "10,000", "100,000", "1,000,000", "100,000,000")
currentList.forEachWithIndex { i, s ->
assertEquals(expectedList[i], s.toCurrency())
}
val exceptionList = listOf("!", "#")
exceptionList.forEach {
try {
it.toCurrency()
}catch (e: NumberFormatException){
assertEquals(NumberFormatException::class, e)
}
}
}
It didn't work and shows failure.
How can I pass the test case? I don't need to check the message but just ExceptionClass.
In toCurrency extension function, you are catching the number format exception and returning the original string. You should rethrow the exception or not to catch it at all.
// ...
catch(e: NumberFormatException) {
// log the exception or ...
throw e
}
Here, let's test only invalid scenario for toCurrency method. It would be easy to determine which test scenario failing or successing.
#Test
fun convertCurrency_invalidNumbers_throwsException() {
val invalidCurrencies = listOf("!", "#")
// check also for big numbers -> 999999999999
assertThrows<NumberFormatException> {
invalidCurrencies.forEach {
it.toCurrency()
}
}
}
#Test
#Throws(NumberFormatException::class)
fun convertCurrency_returnAmericanFormat() {
// test for successful toCurrency conversion
}
Related
// writing junit ExerciseMainLogger class
so how to verify AnalyticsLog.insertEventLog(builder) using Mockito
I have mocked AnalyticsLog class but getting error Actually, there were zero interactions with this mock.
Wanted but not invoked
object ExerciseMainLogger {
fun setLog(eventName: String, screenId: String = "", dimension: Map<String, String> = mapOf()) {
LOG.d(TAG, "setLog - $eventName, $screenId, $dimension")
val builder = LogBuilders.EventBuilder()
.setEventName(eventName)
.setEventType(LogBuilders.EventType.NORMAL)
if (screenId.isNotEmpty()) {
builder.setScreenView(screenId)
}
if (dimension.isNotEmpty()) {
builder.setDimension(dimension)
}
AnalyticsLog.insertEventLog(builder)
}
}
AnalyticsLog Class
object AnalyticsLog {
#JvmStatic
fun insertEventLog(eventBuilder: EventBuilder) {
if (TestConfig.isTestMode()) {
LOG.d(TAG, "[SA] test mode")
return
}
try {
val eventLogs = eventBuilder.build()
val eventId = eventLogs[EVENT_ID_PROPERTY]
val result = insertLog(eventLogs)
if (FeatureManager.getInstance().getBooleanValue(FeatureList.Key.COMMON_DEVELOPER_MODE)) {
LOG.d(TAG, "[SA-DEV] insertEventLog: EventId: $eventId, logs: $eventLogs, send result: $result")
} else {
LOG.d(TAG, "[SA] insertEventLog: EventId: $eventId, send result: $result")
}
} catch (e: Exception) {
LOG.w(TAG, "[SA] insertEventLog exception, " + e.message)
e.printStackTrace()
}
}
}
My Test method looks like below. I trying to run the test case with the JUnit but getting error
mockkStatic(SamsungAnalyticsLog::class)
every { SamsungAnalyticsLog.insertEventLog(builder) } just runs
ExerciseMainLogger.setLog(
ExerciseMainLogger.EX2012,
screenId = screenId,
dimension = dimension
)
verify(exactly = 1) { AnalyticsLog.insertEventLog(builder) }
Verification failed: call 1 of 1: class com.samsung.android.wear.shealth.base.log.SamsungAnalyticsLog.insertEventLog(eq(com.samsung.context.sdk.samsunganalytics.LogBuilders$EventBuilder#71a04ac6))). Only one matching call to SamsungAnalyticsLog(static SamsungAnalyticsLog)/insertEventLog(EventBuilder) happened, but arguments are not matching:
[0]: argument: com.samsung.context.sdk.samsunganalytics.LogBuilders$EventBuilder#7b05129b, matcher: eq(com.samsung.context.sdk.samsunganalytics.LogBuilders$EventBuilder#71a04ac6), result: -
Stack trace:
I'm trying to test a validity function. My function is like this:
class InvalidCredentialException(message: String) : Exception(message)
#Throws
fun credentialValidityChecker(email: String, password: String, nameAndFamily: String? = null) {
when {
email.isBlank() -> {
throw InvalidCredentialException("Email address can't left blank.")
}
!Patterns.EMAIL_ADDRESS.matcher(email)
.matches() -> {
throw InvalidCredentialException("Email address format is not correct.")
}
password.isBlank() -> {
throw InvalidCredentialException("Password can't left blank.")
}
password.length < 5 -> {
throw InvalidCredentialException("Password should have at least 5 characters.")
}
nameAndFamily != null -> {
if (nameAndFamily.isBlank())
throw InvalidCredentialException("Name and family can't left blank.")
}
}
}
I use this function to throw in case of any problem with the user credential. Otherwise, nothing happens, and the code continues. The exception is handled in other application layers.
and here are my test cases:
class CredentialValidityTest {
#Test
fun emptyEmail_raiseEmptyEmailException() {
try {
credentialValidityChecker(email = "", password = "12345")
fail("Empty email should raise exception.")
} catch (e: InvalidCredentialException) {
assertThat(e.message).isEqualTo("Email address can't left blank.")
}
}
#Test
fun wrongFormatEmail_raiseWrongEmailException() {
val wrongFormatEmailList = listOf(
"test", "test#", "test#application",
"test#application.", "test#.", "test.application#com"
)
for (email in wrongFormatEmailList)
try {
credentialValidityChecker(email = email, password = "12345")
fail("Wrong format email should raise exception.")
} catch (e: InvalidCredentialException) {
assertThat(e.message).isEqualTo("Email address format is not correct.")
}
}
#Test
fun emptyPassword_raiseEmptyPasswordException() {
try {
credentialValidityChecker(email = "test#application.com", password = "")
fail("Empty password should raise exception.")
} catch (e: InvalidCredentialException) {
assertThat(e.message).isEqualTo("Password can't left blank.")
}
}
#Test
fun weakPassword_raiseWeakPasswordException() {
try {
credentialValidityChecker(email = "test#application.com", password = "1234")
fail("weak password should raise exception.")
} catch (e: InvalidCredentialException) {
assertThat(e.message).isEqualTo("Password should have at least 5 characters.")
}
}
#Test
fun emptyNameAndFamily_raiseEmptyNameAndFamilyException() {
try {
credentialValidityChecker(
email = "test#application.com",
password = "12345",
nameAndFamily = ""
)
fail("Empty name and family should raise exception.")
} catch (e: InvalidCredentialException) {
assertThat(e.message).isEqualTo("Name and family can't left blank.")
}
}
}
The problem is:
Only the first test case pass, which checks email not be blank. The other test cases fail with the java.lang.NullPointerException error.
What is the problem?
Try using PatternsCompat.EMAIL_ADDRESS instead of Patterns.EMAIL_ADDRESS
I'm new to coroutines and having a hard time figuring out how to correctly wrap an existing callback in a coroutine.
My goal is to be able to do the following:
lifecycleScope.launch {
withContext(Dispatchers.Main) {
val theResult = getPreRollAd() //1. call this suspending func and wait for result
doSomethingWithResult(theResult) //2. now that the result is returned from AdsWizz API (below), do something with it
}
}
Here is the AdsWizz API call that I'd like to "wrap":
val adReqInterface: AdRequestHandlerInterface = object :
AdRequestHandlerInterface {
override fun onResponseError(error: AdswizzSDKError) {
Timber.e("onResponseError $error")
}
override fun onResponseReady(adResponse: AdResponse) {
Timber.d( "onResponseReadySingleAd")
//this contains the url to the ad, title, etc..
!!!*** I WANT TO RETURN THE adResponse.mediaFile?.source string back to "theResult" variable above (in lifecycleScope.launch {.... )
}
}
try {
AdswizzSDK.getAdsLoader().requestAd(adReqParams, adReqInterface)
} catch (e: IllegalArgumentException) {
Timber.d( "IllegalArgumentException")
} catch (e: SecurityException) {
Timber.d( "SecurityException")
} catch (e: Exception) {
Timber.d( "other exception")
e.printStackTrace()
}
I've tried using suspendCoroutine {... to wrap but nothing is working. Really appreciate someones help re the right way to achieve this.
the right way to do it is to use suspendCancellableCoroutine. It can return a result or can be cancelled with an exception.
suspend fun getPreRollAd(): AdResponse {
return suspendCancellableCoroutine {
...
val adReqInterface: AdRequestHandlerInterface = object : AdRequestHandlerInterface {
override fun onResponseError(error: AdswizzSDKError) {
Timber.e("onResponseError $error")
it.cancel(error)
}
override fun onResponseReady(adResponse: AdResponse) {
Timber.d( "onResponseReadySingleAd")
it.resume(adResponse)
}
}
AdswizzSDK.getAdsLoader().requestAd(adReqParams, adReqInterface)
}
}
viewModelScope.launch {
val result = try {
getPreRollAd()
} catch(e: Throwable) {
null
}
...
}
I am trying to fetch a JSONObject "image" that is sometimes a null value, so I set a try {} catch {} for my val jsonMedia in order to make it nullable but Im not sure if I'm missing something because it doesnt seem to work.
Whenever I comment out the jsonMedia my fetch works fine so I'll focus on just sharing the fetch of the "image" so the data I share doesnt get confusing.
1st. Ill show how the "image" is in the database and what I mean by "sometimes" has a null value
- null:
{
"listCar": [
{
//other data
"image": null,
//other data
}
]
}
when it contains an image:
{
"listCar": [
{
//other data
"image": {
"path": "Upload/UploadCarMain/UploadCarMain-200-200/30032235992008220498istanbul_adalarCar195.jpg",
"name": "30032235992008220498istanbul_adalarCar195.jpg"
},
//other data
}
]
}
Now my fetch data was followed by a course I'm watching the only difference is the values of "image" in the database Im using arent like the course which did not contain null values in their image path
Now here is my "Car" class that is supposed to get the image:
class Car(other data, val image: String?, other data) {
override fun toString(): String {
return "Car(//other data, image='$image', //other data')"
}
}
and here is my fetch code where I am trying to try {} catch(){} my "jsonMedia" image JSONOBject:
override fun doInBackground(vararg params: String?): ArrayList<Car> {
Log.d(TAG, "doInBackground starts")
val carList = ArrayList<Car>()
try {
val jsonData = JSONObject(params[0])
val itemsArray = jsonData.getJSONArray("listCar")
for (i in 0 until itemsArray.length()) {
val jsonCar = itemsArray.getJSONObject(i)
//other fetch data
val jsonMedia: JSONObject? = try {jsonCar.getJSONObject("image")} catch (e: IllegalArgumentException) {null}
val photoURL = jsonMedia?.getString("path")
val carObject = Car(other data, photoURL)
carList.add(carObject)
Log.d(TAG, ".doInBackground $carObject")
}
} catch (e: JSONException) {
e.printStackTrace()
Log.e(TAG, "doInBackground: Error processing json data. ${e.message}")
cancel(true)
listener.onError(e)
}
Log.d(TAG, ".doInBackground ends")
return carList
}
override fun onPostExecute(result: ArrayList<Car>) {
Log.d(TAG, "onPostExecute starts")
super.onPostExecute(result)
listener.onDataAvailable(result)
Log.d(TAG, ".onPostExecute ends")
}
}
and here is the error I get when i run the code:
2020-02-14 16:42:16.483 26642-26684/com.example.wasit E/GetFlickrJsonData: doInBackground: Error processing json data. Value null at image of type org.json.JSONObject$1 cannot be converted to JSONObject
Just modify the code like this. Exception class is the Parent class of all exception and provide exact cause of error.
for (i in 0 until itemsArray.length()) {
try {
val jsonCar = itemsArray.getJSONObject(i)
//other fetch data
val jsonMedia: JSONObject? = jsonCar.getJSONObject("image")
val photoURL = jsonMedia?.getString("path")
val carObject = Car(other data, photoURL)
carList.add(carObject)
} catch (ex: Exception) {
Log.d(TAG, ex.localizedMessage.toString())
}
}
I found a way.
I had to wrap my "jsonMedia" in the following try catch:
val jsonMedia: JSONObject? = try {jsonCar.getJSONObject("image")} catch (e: JSONException) {
null
}
Now my images that are null contain placeholders and the others work fine!
following the code, in init function I create a Person object,and have an exception,now I want to stop the progress in catch like java return. How can I do it?
class Person {
val age: String = "10"
private lateinit var person: Person
init {
try {
person = get(2)
} catch (exception: Throwable) {
}
println("----------------do it $person.age")
}
fun get(i: Int): Person {
when (i) {
1 -> {
return Person()
}
else -> {
throw MyException("aaaaaaaaa")
}
}
}
}
If an instance cannot be created due to errors in init, this error shouldn't be suppressed but delegated to the caller. So just do not catch the exception and the init "stopps" automatically.