mirror of
https://github.com/corda/corda.git
synced 2025-02-20 09:26:41 +00:00
CORDA-2345: Updated docs to use the new TestCordapp API, rather than the old scan cordapp packages (#4491)
Also made some improvements to the API, especially for Java users.
This commit is contained in:
parent
ad1a96fefb
commit
f590300cdf
@ -311,70 +311,6 @@ For example:
|
||||
For Contracts that are annotated with ``@NoConstraintPropagation``, the platform requires that the Transaction Builder specifies
|
||||
an actual constraint for the output states (the ``AutomaticPlaceholderConstraint`` can't be used) .
|
||||
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Since all tests involving transactions now require attachments it is also required to load the correct attachments
|
||||
for tests. Unit test environments in JVM ecosystems tend to use class directories rather than JARs, and so CorDapp JARs
|
||||
typically aren't built for testing. Requiring this would add significant complexity to the build systems of Corda
|
||||
and CorDapps, so the test suite has a set of convenient functions to generate CorDapps from package names or
|
||||
to specify JAR URLs in the case that the CorDapp(s) involved in testing already exist. You can also just use
|
||||
``AlwaysAcceptAttachmentConstraint`` in your tests to disable the constraints mechanism.
|
||||
|
||||
MockNetwork/MockNode
|
||||
********************
|
||||
|
||||
The simplest way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to use the
|
||||
``cordappPackages`` constructor parameter (Kotlin) or the ``setCordappPackages`` method on ``MockNetworkParameters`` (Java)
|
||||
when creating the MockNetwork. This will cause the ``AbstractNode`` to use the named packages as sources for CorDapps. All files
|
||||
within those packages will be zipped into a JAR and added to the attachment store and loaded as CorDapps by the
|
||||
``CordappLoader``.
|
||||
|
||||
An example of this usage would be:
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
class SomeTestClass {
|
||||
MockNetwork network = null;
|
||||
|
||||
@Before
|
||||
void setup() {
|
||||
network = new MockNetwork(new MockNetworkParameters().setCordappPackages(Arrays.asList("com.domain.cordapp")))
|
||||
}
|
||||
|
||||
... // Your tests go here
|
||||
}
|
||||
|
||||
|
||||
MockServices
|
||||
************
|
||||
|
||||
If your test uses a ``MockServices`` directly you can instantiate it using a constructor that takes a list of packages
|
||||
to use as CorDapps using the ``cordappPackages`` parameter.
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
MockServices mockServices = new MockServices(Arrays.asList("com.domain.cordapp"))
|
||||
|
||||
However - there is an easier way! If your unit tests are in the same package as the contract code itself, then you
|
||||
can use the no-args constructor of ``MockServices``. The package to be scanned for CorDapps will be the same as the
|
||||
the package of the class that constructed the object. This is a convenient default.
|
||||
|
||||
Driver
|
||||
******
|
||||
|
||||
The driver takes a parameter called ``extraCordappPackagesToScan`` which is a list of packages to use as CorDapps.
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
driver(new DriverParameters().setExtraCordappPackagesToScan(Arrays.asList("com.domain.cordapp"))) ...
|
||||
|
||||
Full Nodes
|
||||
**********
|
||||
|
||||
When testing against full nodes simply place your CorDapp into the cordapps directory of the node.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
If an attachment constraint cannot be resolved, a ``MissingContractAttachments`` exception is thrown. There are two
|
||||
|
@ -22,108 +22,20 @@ A ``MockNetwork`` is created as follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/MockNetworkTestsTutorial.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
class FlowTests {
|
||||
private lateinit var mockNet: MockNetwork
|
||||
.. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/MockNetworkTestsTutorial.java
|
||||
:language: java
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
network = MockNetwork(listOf("my.cordapp.package", "my.other.cordapp.package"))
|
||||
}
|
||||
}
|
||||
The ``MockNetwork`` requires at a minimum a list of CorDapps to be installed on each ``StartedMockNode``. The CorDapps are looked up on the
|
||||
classpath by package name, using ``TestCordapp.findCordapp``.
|
||||
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
public class IOUFlowTests {
|
||||
private MockNetwork network;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
network = new MockNetwork(ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"));
|
||||
}
|
||||
}
|
||||
|
||||
The ``MockNetwork`` requires at a minimum a list of packages. Each package is packaged into a CorDapp JAR and installed
|
||||
as a CorDapp on each ``StartedMockNode``.
|
||||
|
||||
Configuring the ``MockNetwork``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``MockNetwork`` is configured automatically. You can tweak its configuration using a ``MockNetworkParameters``
|
||||
object, or by using named parameters in Kotlin:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
val network = MockNetwork(
|
||||
// A list of packages to scan. Any contracts, flows and Corda services within these
|
||||
// packages will be automatically available to any nodes within the mock network
|
||||
cordappPackages = listOf("my.cordapp.package", "my.other.cordapp.package"),
|
||||
// If true then each node will be run in its own thread. This can result in race conditions in your
|
||||
// code if not carefully written, but is more realistic and may help if you have flows in your app that
|
||||
// do long blocking operations.
|
||||
threadPerNode = false,
|
||||
// The notaries to use on the mock network. By default you get one mock notary and that is usually
|
||||
// sufficient.
|
||||
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)),
|
||||
// If true then messages will not be routed from sender to receiver until you use the
|
||||
// [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can
|
||||
// examine the state of the mock network before and after a message is sent, without races and without
|
||||
// the receiving node immediately sending a response.
|
||||
networkSendManuallyPumped = false,
|
||||
// How traffic is allocated in the case where multiple nodes share a single identity, which happens for
|
||||
// notaries in a cluster. You don't normally ever need to change this: it is mostly useful for testing
|
||||
// notary implementations.
|
||||
servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random())
|
||||
|
||||
val network2 = MockNetwork(
|
||||
// A list of packages to scan. Any contracts, flows and Corda services within these
|
||||
// packages will be automatically available to any nodes within the mock network
|
||||
listOf("my.cordapp.package", "my.other.cordapp.package"), MockNetworkParameters(
|
||||
// If true then each node will be run in its own thread. This can result in race conditions in your
|
||||
// code if not carefully written, but is more realistic and may help if you have flows in your app that
|
||||
// do long blocking operations.
|
||||
threadPerNode = false,
|
||||
// The notaries to use on the mock network. By default you get one mock notary and that is usually
|
||||
// sufficient.
|
||||
notarySpecs = listOf(MockNetworkNotarySpec(DUMMY_NOTARY_NAME)),
|
||||
// If true then messages will not be routed from sender to receiver until you use the
|
||||
// [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can
|
||||
// examine the state of the mock network before and after a message is sent, without races and without
|
||||
// the receiving node immediately sending a response.
|
||||
networkSendManuallyPumped = false,
|
||||
// How traffic is allocated in the case where multiple nodes share a single identity, which happens for
|
||||
// notaries in a cluster. You don't normally ever need to change this: it is mostly useful for testing
|
||||
// notary implementations.
|
||||
servicePeerAllocationStrategy = InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random())
|
||||
)
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
MockNetwork network = MockNetwork(
|
||||
// A list of packages to scan. Any contracts, flows and Corda services within these
|
||||
// packages will be automatically available to any nodes within the mock network
|
||||
ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"),
|
||||
new MockNetworkParameters()
|
||||
// If true then each node will be run in its own thread. This can result in race conditions in
|
||||
// your code if not carefully written, but is more realistic and may help if you have flows in
|
||||
// your app that do long blocking operations.
|
||||
.setThreadPerNode(false)
|
||||
// The notaries to use on the mock network. By default you get one mock notary and that is
|
||||
// usually sufficient.
|
||||
.setNotarySpecs(ImmutableList.of(new MockNetworkNotarySpec(DUMMY_NOTARY_NAME)))
|
||||
// If true then messages will not be routed from sender to receiver until you use the
|
||||
// [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code
|
||||
// that can examine the state of the mock network before and after a message is sent, without
|
||||
// races and without the receiving node immediately sending a response.
|
||||
.setNetworkSendManuallyPumped(false)
|
||||
// How traffic is allocated in the case where multiple nodes share a single identity, which
|
||||
// happens for notaries in a cluster. You don't normally ever need to change this: it is mostly
|
||||
// useful for testing notary implementations.
|
||||
.setServicePeerAllocationStrategy(new InMemoryMessagingNetwork.ServicePeerAllocationStrategy.Random()));
|
||||
``MockNetworkParameters`` provides other properties for the network which can be tweaked. They default to sensible values if not specified.
|
||||
|
||||
Adding nodes to the network
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -132,73 +44,21 @@ Nodes are created on the ``MockNetwork`` using:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/MockNetworkTestsTutorial.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 2
|
||||
:end-before: DOCEND 2
|
||||
|
||||
class FlowTests {
|
||||
private lateinit var mockNet: MockNetwork
|
||||
lateinit var nodeA: StartedMockNode
|
||||
lateinit var nodeB: StartedMockNode
|
||||
.. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/MockNetworkTestsTutorial.java
|
||||
:language: java
|
||||
:start-after: DOCSTART 2
|
||||
:end-before: DOCEND 2
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
network = MockNetwork(listOf("my.cordapp.package", "my.other.cordapp.package"))
|
||||
nodeA = network.createPartyNode()
|
||||
// We can optionally give the node a name.
|
||||
nodeB = network.createPartyNode(CordaX500Name("Bank B", "London", "GB"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. sourcecode:: java
|
||||
|
||||
public class IOUFlowTests {
|
||||
private MockNetwork network;
|
||||
private StartedMockNode a;
|
||||
private StartedMockNode b;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
network = new MockNetwork(ImmutableList.of("my.cordapp.package", "my.other.cordapp.package"));
|
||||
nodeA = network.createPartyNode(null);
|
||||
// We can optionally give the node a name.
|
||||
nodeB = network.createPartyNode(new CordaX500Name("Bank B", "London", "GB"));
|
||||
}
|
||||
}
|
||||
|
||||
Nodes added using ``createPartyNode`` are provided a default set of node parameters. However, it is also possible to
|
||||
provide different parameters to each node using the following methods on ``MockNetwork``:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. sourcecode:: kotlin
|
||||
|
||||
/**
|
||||
* Create a started node with the given parameters.
|
||||
*
|
||||
* @param legalName The node's legal name.
|
||||
* @param forcedID A unique identifier for the node.
|
||||
* @param entropyRoot The initial entropy value to use when generating keys. Defaults to an (insecure) random value,
|
||||
* but can be overridden to cause nodes to have stable or colliding identity/service keys.
|
||||
* @param configOverrides Add/override the default configuration/behaviour of the node
|
||||
* @param extraCordappPackages Extra CorDapp packages to add for this node.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun createNode(legalName: CordaX500Name? = null,
|
||||
forcedID: Int? = null,
|
||||
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
||||
configOverrides: MockNodeConfigOverrides? = null,
|
||||
extraCordappPackages: List<String> = emptyList()
|
||||
): StartedMockNode
|
||||
|
||||
/** Create a started node with the given parameters. **/
|
||||
fun createNode(parameters: MockNodeParameters = MockNodeParameters()): StartedMockNode
|
||||
|
||||
As you can see above, parameters can be added individually or encapsulated within a ``MockNodeParameters`` object. Of
|
||||
particular interest are ``configOverrides`` which allow you to override some of the default node
|
||||
configuration options. Please refer to the ``MockNodeConfigOverrides`` class for details what can currently be overridden.
|
||||
Also, the ``extraCordappPackages`` parameter allows you to add extra CorDapps to a
|
||||
specific node. This is useful when you wish for all nodes to load a common CorDapp but for a subset of nodes to load
|
||||
CorDapps specific to their role in the network.
|
||||
Nodes added using ``createNode`` are provided a default set of node parameters. However, it is also possible to
|
||||
provide different parameters to each node using ``MockNodeParameters``. Of particular interest are ``configOverrides`` which allow you to
|
||||
override some of the default node configuration options. Please refer to the ``MockNodeConfigOverrides`` class for details what can currently
|
||||
be overridden. Also, the ``additionalCordapps`` parameter allows you to add extra CorDapps to a specific node. This is useful when you wish
|
||||
for all nodes to load a common CorDapp but for a subset of nodes to load CorDapps specific to their role in the network.
|
||||
|
||||
Running the network
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -0,0 +1,35 @@
|
||||
package net.corda.docs.java;
|
||||
|
||||
// DOCSTART 1
|
||||
import net.corda.core.identity.CordaX500Name;
|
||||
import net.corda.testing.node.MockNetwork;
|
||||
import net.corda.testing.node.MockNetworkParameters;
|
||||
import net.corda.testing.node.StartedMockNode;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static net.corda.testing.node.TestCordapp.findCordapp;
|
||||
|
||||
public class MockNetworkTestsTutorial {
|
||||
|
||||
private final MockNetwork mockNet = new MockNetwork(new MockNetworkParameters(singletonList(findCordapp("com.mycordapp.package"))));
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
mockNet.stopNodes();
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
// DOCSTART 2
|
||||
private StartedMockNode nodeA;
|
||||
private StartedMockNode nodeB;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
nodeA = mockNet.createNode();
|
||||
// We can optionally give the node a name.
|
||||
nodeB = mockNet.createNode(new CordaX500Name("Bank B", "London", "GB"));
|
||||
}
|
||||
// DOCEND 2
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package net.corda.docs.kotlin
|
||||
|
||||
// DOCSTART 1
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetworkParameters
|
||||
import net.corda.testing.node.StartedMockNode
|
||||
import net.corda.testing.node.TestCordapp.Companion.findCordapp
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
|
||||
class MockNetworkTestsTutorial {
|
||||
|
||||
private val mockNet = MockNetwork(MockNetworkParameters(listOf(findCordapp("com.mycordapp.package"))))
|
||||
|
||||
@After
|
||||
fun cleanUp() {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
// DOCEND 1
|
||||
|
||||
// DOCSTART 2
|
||||
private lateinit var nodeA: StartedMockNode
|
||||
private lateinit var nodeB: StartedMockNode
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
nodeA = mockNet.createNode()
|
||||
// We can optionally give the node a name.
|
||||
nodeB = mockNet.createNode(CordaX500Name("Bank B", "London", "GB"))
|
||||
}
|
||||
// DOCEND 2
|
||||
}
|
@ -269,19 +269,10 @@ Here's an example of it in action from ``FixingFlow.Fixer``.
|
||||
Testing
|
||||
-------
|
||||
|
||||
The ``MockNetwork`` allows the creation of ``MockNode`` instances, which are simplified nodes which can be used for
|
||||
testing (see :doc:`api-testing`). When creating the ``MockNetwork`` you supply a list of packages to scan for CorDapps.
|
||||
Make sure the packages you provide include your oracle service, and it automatically be installed in the test nodes.
|
||||
Then you can create an oracle node on the ``MockNetwork`` and insert any initialisation logic you want to use. In this
|
||||
case, our ``Oracle`` service is in the ``net.corda.irs.api`` package, so the following test setup will install
|
||||
the service in each node. Then an oracle node with an oracle service which is initialised with some data is created on
|
||||
the mock network:
|
||||
|
||||
.. literalinclude:: ../../samples/irs-demo/cordapp/src/test/kotlin/net/corda/irs/api/OracleNodeTearOffTests.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
:dedent: 4
|
||||
The ``MockNetwork`` allows the creation of ``MockNode`` instances, which are simplified nodes which can be used for testing (see :doc:`api-testing`).
|
||||
When creating the ``MockNetwork`` you supply a list of ``TestCordapp`` objects which point to CorDapps on
|
||||
the classpath. These CorDapps will be installed on each node on the network. Make sure the packages you provide reference to the CorDapp
|
||||
containing your oracle service.
|
||||
|
||||
You can then write tests on your mock network to verify the nodes interact with your Oracle correctly.
|
||||
|
||||
|
@ -10,6 +10,7 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.node.MockNetwork
|
||||
import net.corda.testing.node.MockNetworkParameters
|
||||
import net.corda.testing.node.MockNodeParameters
|
||||
import net.corda.testing.node.StartedMockNode
|
||||
import org.junit.After
|
||||
@ -26,7 +27,7 @@ class FlowRegistrationTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
// no cordapps scanned so it can be tested in isolation
|
||||
mockNetwork = MockNetwork()
|
||||
mockNetwork = MockNetwork(MockNetworkParameters())
|
||||
initiator = mockNetwork.createNode(MockNodeParameters(legalName = CordaX500Name("initiator", "Reading", "GB")))
|
||||
responder = mockNetwork.createNode(MockNodeParameters(legalName = CordaX500Name("responder", "Reading", "GB")))
|
||||
mockNetwork.runNetwork()
|
||||
|
@ -68,7 +68,7 @@ class OracleNodeTearOffTests {
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
// DOCSTART 2
|
||||
// DOCSTART 1
|
||||
@Test
|
||||
fun `verify that the oracle signs the transaction if the interest rate within allowed limit`() {
|
||||
// Create a partial transaction
|
||||
@ -93,7 +93,7 @@ class OracleNodeTearOffTests {
|
||||
// Check that the transaction has been signed by the oracle
|
||||
assertContains(fix.signers, oracle.owningKey)
|
||||
}
|
||||
// DOCEND 2
|
||||
// DOCEND 1
|
||||
|
||||
@Test
|
||||
fun `verify that the oracle rejects the transaction if the interest rate is outside the allowed limit`() {
|
||||
|
@ -10,7 +10,7 @@ class MockNetworkIntegrationTests {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
MockNetwork().run {
|
||||
MockNetwork(MockNetworkParameters()).run {
|
||||
repeat(2) { createNode() }
|
||||
runNetwork()
|
||||
stopNodes()
|
||||
|
@ -248,7 +248,9 @@ data class DriverParameters(
|
||||
val notaryCustomOverrides: Map<String, Any?> = emptyMap(),
|
||||
val inMemoryDB: Boolean = true,
|
||||
val cordappsForAllNodes: Collection<TestCordapp>? = null
|
||||
) {
|
||||
) {
|
||||
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(isDebug = false, cordappsForAllNodes = cordappsForAllNodes)
|
||||
|
||||
constructor(
|
||||
isDebug: Boolean = false,
|
||||
driverDirectory: Path = Paths.get("build") / "node-driver" / getTimestampAsDirectoryName(),
|
||||
@ -313,38 +315,6 @@ data class DriverParameters(
|
||||
cordappsForAllNodes = null
|
||||
)
|
||||
|
||||
constructor(
|
||||
isDebug: Boolean,
|
||||
driverDirectory: Path,
|
||||
portAllocation: PortAllocation,
|
||||
debugPortAllocation: PortAllocation,
|
||||
systemProperties: Map<String, String>,
|
||||
useTestClock: Boolean,
|
||||
startNodesInProcess: Boolean,
|
||||
waitForAllNodesToFinish: Boolean,
|
||||
notarySpecs: List<NotarySpec>,
|
||||
extraCordappPackagesToScan: List<String>,
|
||||
jmxPolicy: JmxPolicy,
|
||||
networkParameters: NetworkParameters,
|
||||
cordappsForAllNodes: Collection<TestCordapp>? = null
|
||||
) : this(
|
||||
isDebug,
|
||||
driverDirectory,
|
||||
portAllocation,
|
||||
debugPortAllocation,
|
||||
systemProperties,
|
||||
useTestClock,
|
||||
startNodesInProcess,
|
||||
waitForAllNodesToFinish,
|
||||
notarySpecs,
|
||||
extraCordappPackagesToScan,
|
||||
jmxPolicy,
|
||||
networkParameters,
|
||||
emptyMap(),
|
||||
true,
|
||||
cordappsForAllNodes
|
||||
)
|
||||
|
||||
constructor(
|
||||
isDebug: Boolean,
|
||||
driverDirectory: Path,
|
||||
@ -377,39 +347,6 @@ data class DriverParameters(
|
||||
cordappsForAllNodes = null
|
||||
)
|
||||
|
||||
constructor(
|
||||
isDebug: Boolean,
|
||||
driverDirectory: Path,
|
||||
portAllocation: PortAllocation,
|
||||
debugPortAllocation: PortAllocation,
|
||||
systemProperties: Map<String, String>,
|
||||
useTestClock: Boolean,
|
||||
startNodesInProcess: Boolean,
|
||||
waitForAllNodesToFinish: Boolean,
|
||||
notarySpecs: List<NotarySpec>,
|
||||
extraCordappPackagesToScan: List<String>,
|
||||
jmxPolicy: JmxPolicy,
|
||||
networkParameters: NetworkParameters,
|
||||
inMemoryDB: Boolean,
|
||||
cordappsForAllNodes: Set<TestCordapp>? = null
|
||||
) : this(
|
||||
isDebug,
|
||||
driverDirectory,
|
||||
portAllocation,
|
||||
debugPortAllocation,
|
||||
systemProperties,
|
||||
useTestClock,
|
||||
startNodesInProcess,
|
||||
waitForAllNodesToFinish,
|
||||
notarySpecs,
|
||||
extraCordappPackagesToScan,
|
||||
jmxPolicy,
|
||||
networkParameters,
|
||||
emptyMap(),
|
||||
inMemoryDB,
|
||||
cordappsForAllNodes
|
||||
)
|
||||
|
||||
fun withIsDebug(isDebug: Boolean): DriverParameters = copy(isDebug = isDebug)
|
||||
fun withDriverDirectory(driverDirectory: Path): DriverParameters = copy(driverDirectory = driverDirectory)
|
||||
fun withPortAllocation(portAllocation: PortAllocation): DriverParameters = copy(portAllocation = portAllocation)
|
||||
@ -419,6 +356,8 @@ data class DriverParameters(
|
||||
fun withStartNodesInProcess(startNodesInProcess: Boolean): DriverParameters = copy(startNodesInProcess = startNodesInProcess)
|
||||
fun withWaitForAllNodesToFinish(waitForAllNodesToFinish: Boolean): DriverParameters = copy(waitForAllNodesToFinish = waitForAllNodesToFinish)
|
||||
fun withNotarySpecs(notarySpecs: List<NotarySpec>): DriverParameters = copy(notarySpecs = notarySpecs)
|
||||
@Deprecated("extraCordappPackagesToScan does not preserve the original CorDapp's versioning and metadata, which may lead to " +
|
||||
"misleading results in tests. Use withCordappsForAllNodes instead.")
|
||||
fun withExtraCordappPackagesToScan(extraCordappPackagesToScan: List<String>): DriverParameters = copy(extraCordappPackagesToScan = extraCordappPackagesToScan)
|
||||
fun withJmxPolicy(jmxPolicy: JmxPolicy): DriverParameters = copy(jmxPolicy = jmxPolicy)
|
||||
fun withNetworkParameters(networkParameters: NetworkParameters): DriverParameters = copy(networkParameters = networkParameters)
|
||||
|
@ -61,8 +61,7 @@ data class MockNodeParameters(
|
||||
}
|
||||
|
||||
/**
|
||||
* Immutable builder for configuring a [MockNetwork]. Kotlin users can also use named parameters to the constructor
|
||||
* of [MockNetwork], which is more convenient.
|
||||
* Immutable builder for configuring a [MockNetwork].
|
||||
*
|
||||
* @property networkSendManuallyPumped If false then messages will not be routed from sender to receiver until you use
|
||||
* the [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can examine the
|
||||
@ -95,6 +94,8 @@ data class MockNetworkParameters(
|
||||
networkParameters: NetworkParameters
|
||||
) : this(networkSendManuallyPumped, threadPerNode, servicePeerAllocationStrategy, notarySpecs, networkParameters, emptyList())
|
||||
|
||||
constructor(cordappsForAllNodes: Collection<TestCordapp>) : this(threadPerNode = false, cordappsForAllNodes = cordappsForAllNodes)
|
||||
|
||||
fun withNetworkParameters(networkParameters: NetworkParameters): MockNetworkParameters = copy(networkParameters = networkParameters)
|
||||
fun withNetworkSendManuallyPumped(networkSendManuallyPumped: Boolean): MockNetworkParameters = copy(networkSendManuallyPumped = networkSendManuallyPumped)
|
||||
fun withThreadPerNode(threadPerNode: Boolean): MockNetworkParameters = copy(threadPerNode = threadPerNode)
|
||||
@ -108,7 +109,8 @@ data class MockNetworkParameters(
|
||||
threadPerNode: Boolean,
|
||||
servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy,
|
||||
notarySpecs: List<MockNetworkNotarySpec>,
|
||||
networkParameters: NetworkParameters): MockNetworkParameters {
|
||||
networkParameters: NetworkParameters
|
||||
): MockNetworkParameters {
|
||||
return MockNetworkParameters(networkSendManuallyPumped, threadPerNode, servicePeerAllocationStrategy, notarySpecs, networkParameters, emptyList())
|
||||
}
|
||||
}
|
||||
@ -243,9 +245,9 @@ class StartedMockNode private constructor(private val node: TestStartedNode) {
|
||||
* By default a single notary node is automatically started, which forms part of the network parameters for all the nodes.
|
||||
* This node is available by calling [defaultNotaryNode].
|
||||
*
|
||||
* @property defaultParameters The default parameters for the network. If any of the remaining constructor parameters are specified then
|
||||
* their values are taken instead of the corresponding value in [defaultParameters].
|
||||
* @property cordappPackages A [List] of cordapp packages to scan for any cordapp code, e.g. contract verification code, flows and services.
|
||||
* @property defaultParameters A [MockNetworkParameters] object which contains the same parameters as the constructor, provided
|
||||
* as a convenience for Java users.
|
||||
* @property networkSendManuallyPumped If false then messages will not be routed from sender to receiver until you use
|
||||
* the [MockNetwork.runNetwork] method. This is useful for writing single-threaded unit test code that can examine the
|
||||
* state of the mock network before and after a message is sent, without races and without the receiving node immediately
|
||||
@ -279,8 +281,7 @@ open class MockNetwork(
|
||||
cordappPackages, defaultParameters = parameters
|
||||
)
|
||||
|
||||
@JvmOverloads
|
||||
constructor(parameters: MockNetworkParameters = MockNetworkParameters()) : this(emptyList(), parameters)
|
||||
constructor(parameters: MockNetworkParameters) : this(emptyList(), defaultParameters = parameters)
|
||||
|
||||
private val internalMockNetwork = InternalMockNetwork(
|
||||
cordappPackages,
|
||||
@ -317,7 +318,7 @@ open class MockNetwork(
|
||||
fun createPartyNode(legalName: CordaX500Name? = null): StartedMockNode = StartedMockNode.create(internalMockNetwork.createPartyNode(legalName))
|
||||
|
||||
/** Create a started node with the given parameters. **/
|
||||
fun createNode(parameters: MockNodeParameters = MockNodeParameters()): StartedMockNode {
|
||||
fun createNode(parameters: MockNodeParameters): StartedMockNode {
|
||||
return StartedMockNode.create(internalMockNetwork.createNode(InternalMockNodeParameters(parameters)))
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import net.corda.testing.driver.NodeParameters
|
||||
import net.corda.testing.node.internal.TestCordappImpl
|
||||
|
||||
/**
|
||||
* Encapsulates a CorDapp that exists on the current classpath, which can be pulled in for testing. Use [TestCordapp.Factory.findCordapp]
|
||||
* Encapsulates a CorDapp that exists on the current classpath, which can be pulled in for testing. Use [TestCordapp.findCordapp]
|
||||
* to locate an existing CorDapp.
|
||||
*
|
||||
* @see DriverParameters.cordappsForAllNodes
|
||||
@ -15,27 +15,25 @@ import net.corda.testing.node.internal.TestCordappImpl
|
||||
* @see MockNodeParameters.additionalCordapps
|
||||
*/
|
||||
@DoNotImplement
|
||||
interface TestCordapp {
|
||||
abstract class TestCordapp {
|
||||
/** The package used to find the CorDapp. This may not be the root package of the CorDapp. */
|
||||
val scanPackage: String
|
||||
abstract val scanPackage: String
|
||||
|
||||
/** Returns the config for on this CorDapp, defaults to empty if not specified. */
|
||||
val config: Map<String, Any>
|
||||
abstract val config: Map<String, Any>
|
||||
|
||||
/** Returns a copy of this [TestCordapp] but with the specified CorDapp config. */
|
||||
fun withConfig(config: Map<String, Any>): TestCordapp
|
||||
abstract fun withConfig(config: Map<String, Any>): TestCordapp
|
||||
|
||||
class Factory {
|
||||
companion object {
|
||||
/**
|
||||
* Scans the current classpath to find the CorDapp that contains the given package. All the CorDapp's metdata present in its
|
||||
* MANIFEST are inherited. If more than one location containing the package is found then an exception is thrown. An exception
|
||||
* is also thrown if no CorDapp is found.
|
||||
*
|
||||
* @param scanPackage The package name used to find the CorDapp. This does not need to be the root package.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun findCordapp(scanPackage: String): TestCordapp = TestCordappImpl(scanPackage = scanPackage, config = emptyMap())
|
||||
}
|
||||
companion object {
|
||||
/**
|
||||
* Scans the current classpath to find the CorDapp that contains the given package. All the CorDapp's metdata present in its
|
||||
* MANIFEST are inherited. If more than one location containing the package is found then an exception is thrown. An exception
|
||||
* is also thrown if no CorDapp is found.
|
||||
*
|
||||
* @param scanPackage The package name used to find the CorDapp. This does not need to be the root package of the CorDapp.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun findCordapp(scanPackage: String): TestCordapp = TestCordappImpl(scanPackage = scanPackage, config = emptyMap())
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ data class CustomCordapp(
|
||||
val classes: Set<Class<*>> = emptySet(),
|
||||
val signingInfo: SigningInfo? = null,
|
||||
override val config: Map<String, Any> = emptyMap()
|
||||
) : TestCordappInternal {
|
||||
) : TestCordappInternal() {
|
||||
init {
|
||||
require(packages.isNotEmpty() || classes.isNotEmpty()) { "At least one package or class must be specified" }
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ import kotlin.streams.toList
|
||||
/**
|
||||
* Implementation of the public [TestCordapp] API.
|
||||
*
|
||||
* As described in [TestCordapp.Factory.findCordapp], this represents a single CorDapp jar on the current classpath. The [scanPackage] may
|
||||
* As described in [TestCordapp.findCordapp], this represents a single CorDapp jar on the current classpath. The [scanPackage] may
|
||||
* be for an external dependency to the project that's using this API, in which case that dependency jar is referenced as is. On the other hand,
|
||||
* the [scanPackage] may reference a gradle CorDapp project on the local system. In this scenerio the project's "jar" task is executed to
|
||||
* build the CorDapp jar. This allows us to inherit the CorDapp's MANIFEST information without having to do any extra processing.
|
||||
*/
|
||||
data class TestCordappImpl(override val scanPackage: String, override val config: Map<String, Any>) : TestCordappInternal {
|
||||
data class TestCordappImpl(override val scanPackage: String, override val config: Map<String, Any>) : TestCordappInternal() {
|
||||
override fun withConfig(config: Map<String, Any>): TestCordappImpl = copy(config = config)
|
||||
|
||||
override fun withOnlyJarContents(): TestCordappImpl = copy(config = emptyMap())
|
||||
@ -27,9 +27,11 @@ data class TestCordappImpl(override val scanPackage: String, override val config
|
||||
get() {
|
||||
val jars = TestCordappImpl.findJars(scanPackage)
|
||||
when (jars.size) {
|
||||
0 -> throw IllegalArgumentException("Package $scanPackage does not exist")
|
||||
0 -> throw IllegalArgumentException("There are no CorDapps containing the package $scanPackage on the classpath. Make sure " +
|
||||
"the package name is correct and that the CorDapp is added as a gradle dependency.")
|
||||
1 -> return jars.first()
|
||||
else -> throw IllegalArgumentException("More than one jar found containing package $scanPackage: $jars")
|
||||
else -> throw IllegalArgumentException("There is more than one CorDapp containing the package $scanPackage on the classpath " +
|
||||
"$jars. Specify a package name which is unique to the CorDapp.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||
*
|
||||
* @property jarFile The jar file this CorDapp represents. Different CorDapps may point to the same file.
|
||||
*/
|
||||
interface TestCordappInternal : TestCordapp {
|
||||
val jarFile: Path
|
||||
abstract class TestCordappInternal : TestCordapp() {
|
||||
abstract val jarFile: Path
|
||||
|
||||
/** Return a copy of this TestCordappInternal but without any metadata, such as configs and signing information. */
|
||||
fun withOnlyJarContents(): TestCordappInternal
|
||||
abstract fun withOnlyJarContents(): TestCordappInternal
|
||||
|
||||
companion object {
|
||||
fun installCordapps(baseDirectory: Path,
|
||||
|
@ -44,9 +44,9 @@ fun cordappForClasses(vararg classes: Class<*>): CustomCordapp = CustomCordapp(p
|
||||
|
||||
/**
|
||||
* Find the single CorDapp jar on the current classpath which contains the given package. This is a convenience method for
|
||||
* [TestCordapp.Factory.findCordapp] but returns the internal [TestCordappImpl].
|
||||
* [TestCordapp.findCordapp] but returns the internal [TestCordappImpl].
|
||||
*/
|
||||
fun findCordapp(scanPackage: String): TestCordappImpl = TestCordapp.Factory.findCordapp(scanPackage) as TestCordappImpl
|
||||
fun findCordapp(scanPackage: String): TestCordappImpl = TestCordapp.findCordapp(scanPackage) as TestCordappImpl
|
||||
|
||||
fun getCallerClass(directCallerClass: KClass<*>): Class<*>? {
|
||||
val stackTrace = Throwable().stackTrace
|
||||
|
@ -16,7 +16,7 @@ class MockNetworkTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNetwork = MockNetwork()
|
||||
mockNetwork = MockNetwork(MockNetworkParameters())
|
||||
}
|
||||
|
||||
@After
|
||||
|
Loading…
x
Reference in New Issue
Block a user