Rickky13
Rickky13

Reputation: 431

Corda with mockito_kotlin for unit test

Hi I am trying to mock a Offchain/ API hit that is querying a offchain database / sepaarate external system. however i am facing problems when using mockito_kotlin to mock the response from the functions, it seems like the portion was not taken up during the starting of different nodes.

Is there any example or ways to perform this?

Edited:

I have a function callExternalService() which will return a string from offLedger service

class ExternalService {
  fun callExternalService() : String {
      // Call external service
      return externalResult
  }
}

I mocked the class using Mockito before the execution of flow as below:

val externalService = Mockito.mock(ExternalService::class.java)
Mockito.doReturn("Hello").`when`(externalService.callExternalService()).toString()

I have tried to call to the mocked callExternalService() during the flow and after the FinalityFlow to get some mock data. However when the unit test runs, the mocked class is not injected and the "Hello" is not returned from the class.

Hence, i was suspecting that the mock function is not taken into the nodes during the base start-nodes sequence, as it was still trying to hit an external service where I do not want to involve another external system for unit test purposes.

Upvotes: 1

Views: 462

Answers (1)

Joel
Joel

Reputation: 23140

Suppose you have the following service:

@CordaService
class ExternalService: SingletonSerializeAsToken() {
    fun callExternalService() : String {
        val externalResult = TODO("Call external service")
        return externalResult
    }
}

You'd need to pull the call to the service out into a separate function in your flow. Make this separate function and the flow class itself open, so that they can be overridden:

@InitiatingFlow
@StartableByRPC
open class RealFlow : FlowLogic<String>() {
    @Suspendable
    override fun call(): String {
        return queryService()
    }

    @Suspendable
    open fun queryService(): String {
        return serviceHub.cordaService(ExternalService::class.java).callExternalService()
    }
}

Now create a test subclass of the flow that overrides queryService to return dummy data instead of calling out to an API:

class TestFlow : RealFlow() {
    override fun queryService(): String {
        return "dummyData"
    }
}

You can now use TestFlow in flow tests to test the functionality of the main flow:

@Test
fun `example test`() {
    val flow = TestFlow()
    val future = node.services.startFlow(flow).resultFuture
    network.runNetwork()
    val externalResult = future.getOrThrow()
    assertEquals("dummyData", externalResult)
}

Upvotes: 1

Related Questions