CORDA-2503: Added installCordaService to UnstartedMockNode to allow tests with custom test-only services (#4655)

This commit is contained in:
Shams Asari 2019-01-28 13:49:01 +00:00 committed by GitHub
parent 631f04e348
commit fc7428a40d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 2 deletions

View File

@ -9,6 +9,8 @@ Unreleased
* Updating postgres dependency to 42.2.5
* Test ``CordaService`` s can be installed on mock nodes using ``UnstartedMockNode.installCordaService``.
.. _changelog_v4.0:
Version 4.0

View File

@ -573,7 +573,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
val loadedServices = cordappLoader.cordapps.flatMap { it.services }
loadedServices.forEach {
try {
installCordaService(flowStarter, it)
installCordaService(it)
} catch (e: NoSuchMethodException) {
log.error("${it.name}, as a Corda service, must have a constructor with a single parameter of type " +
ServiceHub::class.java.name)
@ -637,7 +637,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
override fun hashCode() = Objects.hash(serviceHub, flowStarter, serviceInstance)
}
private fun <T : SerializeAsToken> installCordaService(flowStarter: FlowStarter, serviceClass: Class<T>) {
fun <T : SerializeAsToken> installCordaService(serviceClass: Class<T>): T {
serviceClass.requireAnnotation<CordaService>()
val service = try {
@ -659,6 +659,8 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
service.tokenize()
log.info("Installed ${serviceClass.name} Corda service")
return service
}
private fun registerCordappFlows() {

View File

@ -11,6 +11,8 @@ import net.corda.core.internal.uncheckedCast
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceHub
import net.corda.core.node.services.CordaService
import net.corda.core.serialization.SerializeAsToken
import net.corda.core.utilities.getOrThrow
import net.corda.node.services.config.NodeConfiguration
import net.corda.testing.common.internal.testNetworkParameters
@ -137,6 +139,15 @@ class UnstartedMockNode private constructor(private val node: InternalMockNetwor
/** An identifier for the node. By default this is allocated sequentially in a [MockNetwork] **/
val id get() : Int = node.id
/**
* Install a custom test-only [CordaService].
*
* NOTE: There is no need to call this method if the service class is defined in the CorDapp and the [TestCordapp] API is used.
*
* @return the instance of the service object.
*/
fun <T : SerializeAsToken> installCordaService(serviceClass: Class<T>): T = node.installCordaService(serviceClass)
/**
* Start the node
*
@ -180,6 +191,8 @@ class StartedMockNode private constructor(private val node: TestStartedNode) {
/**
* Manually register an initiating-responder flow pair based on the [FlowLogic] annotations.
*
* NOTE: There is no need to call this method if the flow pair is defined in the CorDapp and the [TestCordapp] API is used.
*
* @param initiatedFlowClass [FlowLogic] class which is annotated with [InitiatedBy].
* @return An [Observable] which emits responder flows each time one is executed.
*/

View File

@ -1,5 +1,16 @@
package net.corda.testing.node
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party
import net.corda.core.node.AppServiceHub
import net.corda.core.node.services.CordaService
import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.unwrap
import net.corda.testing.core.*
import org.assertj.core.api.Assertions.*
import org.junit.After
@ -44,4 +55,34 @@ class MockNetworkTest {
val ex = assertFailsWith<IllegalStateException> { unstarted.started }
assertThat(ex).hasMessage("Node ID=$NODE_ID is not running")
}
@Test
fun installCordaService() {
val unstarted = mockNetwork.createUnstartedNode()
assertThat(unstarted.installCordaService(TestService::class.java)).isNotNull()
val started = unstarted.start()
started.registerInitiatedFlow(TestResponder::class.java)
val future = started.startFlow(TestInitiator(started.info.singleIdentity()))
mockNetwork.runNetwork()
assertThat(future.getOrThrow()).isEqualTo(TestService::class.java.name)
}
@CordaService
class TestService(services: AppServiceHub) : SingletonSerializeAsToken()
@InitiatingFlow
class TestInitiator(private val party: Party) : FlowLogic<String>() {
@Suspendable
override fun call(): String {
return initiateFlow(party).receive<String>().unwrap { it }
}
}
@InitiatedBy(TestInitiator::class)
class TestResponder(private val otherSide: FlowSession) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
otherSide.send(serviceHub.cordaService(TestService::class.java).javaClass.name)
}
}
}