如何在Corda中隔离Acceptor Flow进行单元测试并验证无效交易处理?
如何单独测试Corda接收方流程(跳过发起方流程)
完全理解你的需求——当发起方流程会提前拦截无效交易时,确实需要直接针对接收方流程做单独测试,验证它能否正确拒绝合约验证失败的交易。下面是具体的实现步骤和代码示例:
1. 搭建基础测试环境
首先用Corda的TestDSL初始化测试节点,包括接收方节点和一个模拟的发起方节点(不需要启动它的流程,只是用来生成签名):
class AcceptorFlowTests : MockNetworkTest() { private lateinit var acceptorNode: StartedNode<MockNode> private lateinit var initiatorNode: StartedNode<MockNode> override fun setup() { super.setup() val nodes = network.createNodes(listOf(acceptorIdentity, initiatorIdentity)) acceptorNode = nodes.single { it.info.legalIdentities.first() == acceptorIdentity } initiatorNode = nodes.single { it.info.legalIdentities.first() == initiatorIdentity } } }
2. 手动构造无效的SignedTransaction
我们需要创建一个结构完整但合约验证失败的交易,然后让发起方节点对其签名(模拟发起方流程的签名步骤):
private fun createInvalidSignedTransaction(): SignedTransaction { // 1. 创建一个违反合约规则的输出状态 val invalidState = MyState( value = -100, // 假设合约要求value必须大于0 owner = acceptorIdentity, participants = listOf(initiatorIdentity, acceptorIdentity) ) // 2. 构建交易组件 val txBuilder = TransactionBuilder(notary) .addOutputState(invalidState, MY_CONTRACT_ID) .addCommand(MyContract.Commands.Action(), listOf(initiatorIdentity.owningKey, acceptorIdentity.owningKey)) // 3. 发起方节点签名(模拟发起方完成的步骤) val partiallySignedTx = initiatorNode.services.signInitialTransaction(txBuilder) return partiallySignedTx }
这里的关键是确保交易的结构是合法的(有正确的命令、参与者、公证人),但输出状态违反合约的验证规则——这样发起方流程如果正常运行会在verify()步骤报错,但我们手动跳过发起方流程,直接把这个部分签名的交易传给接收方。
3. 启动接收方流程并验证结果
现在直接在接收方节点上启动Acceptor Flow,传入这个无效的交易,然后断言流程是否按预期拒绝:
@Test fun `acceptor flow should reject transaction with invalid contract state`() { val invalidStx = createInvalidSignedTransaction() // 启动接收方流程 val flow = AcceptorFlow(invalidStx) val future = acceptorNode.startFlow(flow) network.runNetwork() // 断言流程抛出合约验证异常 val exception = assertThrows<TransactionVerificationException> { future.get() } assert(exception.message?.contains("Contract verification failed") == true) }
关键注意事项
- 确保你的Acceptor Flow在处理交易时,会调用
serviceHub.verifyTransaction(stx)或者在签名前执行合约验证——这是接收方拒绝无效交易的核心步骤。 - 如果你的Acceptor Flow依赖发起方的某些消息(比如交易的提议),可以手动构造对应的消息对象传入,不需要依赖发起方流程的触发。
- 测试时要覆盖不同类型的合约失败场景(比如输入状态验证失败、命令不匹配等),确保接收方流程都能正确处理。
内容的提问来源于stack exchange,提问作者BrianRice
相关产品推荐
相关产品推荐

