2

I followed step by step instructions from many blogs for implementing a mock with MockK:

class SWServiceImplTest {

    @MockK
    lateinit var externalApi: ExternalApiService

    @InjectMockKs
    lateinit var SWService: SWServiceImpl

    @Before
    fun setUp() = MockKAnnotations.init(this)

    @Test
    fun SWCharacterReturnsCorrectValues() {

        every { externalApi.get<Characters>(Utils.SW_API) } returns mockCharacters()

        val result = SWService.swCharacter!!
        assertEquals("blue", result.first().color?.toLowerCase())
        assertEquals(result.size, 3)
    }

}

I want to inject externalApi into my SWService service and mock the get method of the injected object (externalApi) but it seems that the mock is ignored.

logs :

15:09:54.497 [main] DEBUG io.mockk.impl.instantiation.AbstractMockFactory - Creating mockk for <error "java.lang.NoClassDefFoundError: kotlin/coroutines/intrinsics/IntrinsicsKt"> name=externalApi#1
15:09:56.820 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP GET https://xxx.xxx/
15:09:57.038 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[application/json, application/*+json]

org.springframework.web.client.RestClientException: No HttpMessageConverter for java.lang.Object and content type ""

In my SWService file, externalApi is initialized in a companion object :

    companion object{
        val api = ExternalApiService()
    }

Something wrong in my implementation ? Thanks

johann
  • 1,001
  • 7
  • 30
  • 55
  • How you are initializing `externalApi` in `SWService` class? Could you paste that code too? – Suryavel TR Jul 24 '19 at 07:27
  • Thanks @SuryavelTR for your comment. I've updated my message : It's initialized in a companion object in my class – johann Jul 24 '19 at 08:07
  • Deleted a comment. Missed the point about InjectMocks SWService. So. You are not able to InjectMocks into companion object. I would suggest to have `api` something alike `lateinit var` as a field or `val` in the constructor(believe this one works as well) – oleksiyp Jul 24 '19 at 08:23
  • Does this answer your question? [How to mock a Kotlin singleton object?](https://stackoverflow.com/questions/37977320/how-to-mock-a-kotlin-singleton-object) – LeoColman Dec 19 '19 at 17:15

1 Answers1

1

Kotlin generates a inner class for companion object {} called Companion. This Companion class would have only getters for the fields declared (in your case getApi()). But the field is maintained by outer class SWService.

So equivalent java class for SWService would look like.

public final class SWService {
   private static final ExternalApiService api = new ExternalApiService();

   public static final class Companion() {
       public final ExternalApiService getApi() {
          return SWService.api;
       }
   }
}

Now you want to mock api which is static field. This can be done using powermockito.

Add this dependency,

testImplementation "org.powermock:powermock-api-mockito2:2.0.0-beta.5"

And in your test,

public final class SWServiceTest {

   @MockK
   lateinit var api: ExternalApiService

   var service = SWService()

    @Before
    fun setUp() {
        MockKAnnotations.init(this)
        Whitebox.setInternalState(SWService::class.java,"api", api);
    }
}

Hope it helps.

Suryavel TR
  • 3,062
  • 1
  • 18
  • 23
  • Thanks for your reply. I tried to implement with `powermock` but I'm still getting the same error... (Creating mockk for – johann Jul 24 '19 at 09:40