1

I have read it here. It is close to my problem and I need more guidance on this part.

Given,

class Journey{
    fun start(){
        Service.getInstance().getProductInfo(activity,object: Service.Callback<Product>{
            override fun onSuccess(data: Product) {
                showProductInfo(activity, data, customer)
            }

            override fun onError(e: Throwable) {
                showError(e)
            }
        })
    }

}

and I want to mock Service.getProductInfo and perform happy path and unhappy path handling, how do I do it with mockk?

Additional question, is there a way to exclude certain function like start above in jacoco? Sometimes some functions has not much meaning for unit test and excluding it in jacoco makes much more sense.

UPDATE:

I learnt from Gradle website that it does not currently support method exclusion.

Callback interface is below

interface Callback<T>{
   fun onSuccess(data: T)
   fun onError(e: Throwable)
}

I'm using retrofit for Service.

hjchin
  • 864
  • 2
  • 8
  • 25

1 Answers1

0

First, you don't want to exclude your code from code coverage check, because it is your own code and it has to be tested.

For the main problem. In this particular (because mainly I would not use this design at all) case I would go with the way of having ability to mock getInstance method first, so it would return any mock you want to use in your tests. First thing that come to mind is using PowerMockito (or similar mocking frameworks). PowerMockito allows you to mock static method (see https://github.com/powermock/powermock/wiki/mockstatic) or, which is a bit worse in my mind, but is totally up to you) mock construction of object inside factory method with https://github.com/powermock/powermock/wiki/MockConstructor

My least favorite approach (if you somehow cannot use PowerMock in your code) to do so (as far as I understand it is static method of Service class) can be found here: https://hackernoon.com/mocking-static-method-in-kotlin-614df89482ae It is pretty simple but you will need to rewrite you code to use it. But if can rewrite your code, it is better to redesign it to make it more testable.

Edit: just realized that you needed to do it with mockk. I'm not really experienced with it, but AFAIK it has almost same fucntionality with staticMockk. You can see this question to check it: Mock static java methods using Mockk

  • Thanks for the reply. object mocking in mockk is simple with mockkObject. I have no problem with getInstance(). I would like to know how to mock the callback. Thanks. For kotlin, it is much easier to use mockk. Powermockito gave me a lot of problem with Kotlin. It works only with Java. – hjchin Jun 24 '19 at 14:39
  • Can you provide some information **Service** class and especially its **Callback** (field, subclass?)? Probably there is a way to mock it. – Alexey.Efimov Jun 24 '19 at 15:34
  • Callback is an interface with 2 functions and a given data type. I update the question – hjchin Jun 25 '19 at 00:54
  • Okay now I got it. Personally I would split it into testing getProductInfo separately from start method (you can instantiate instance of service and pass your own activity and callback with needed assertions) and then tested start method with mocked getProductInfo method by itself without callback logic. It is really questionable if you need to test this callback separately, I would just test methods it calls. – Alexey.Efimov Jun 25 '19 at 11:06
  • thanks for helping. I think you might not getting my question right or I have not explain my question clearly. My question is not about the design but the syntax in mockk to mock callback which has 2 functions. – hjchin Jun 25 '19 at 16:47