mirror of
https://github.com/corda/corda.git
synced 2025-04-08 03:44:49 +00:00
CORDA-2503: Added installCordaService to UnstartedMockNode to allow tests with custom test-only services (#4655)
This commit is contained in:
parent
631f04e348
commit
fc7428a40d
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user