Stefano.Maffullo
Stefano.Maffullo

Reputation: 841

Contract Testing DSL wrong behaviour / bug

I'm writing a Contract Test for my CorDapp but I'm stuck at a point because it isn't behaving as it should.

This is the contract code (only the relevant part is presented)

when (command.value ) {
        is LoanCommands.Issue -> requireThat {
            "No Inputs should be consumed when issuing a Loan" using ( tx.inputs.isEmpty())
            "Only a single output must be created when issugin a Loan" using (tx.outputs.size == 1)
            "Outputs must not be empty" using (tx.outputs.isNotEmpty()) 

Then this is the test that I'm running

    @Test
fun issueTransactionMustHaveOneOutputOfTypeLoanContract() {

    ledger {
        transaction {
            command(loanState.issuer.owningKey) { LoanContract.LoanCommands.Issue() }
            timeWindow(ZonedDateTime.of(LocalDate.now(), time, zoneId).toInstant())

            this `fails with` "Outputs must not be empty"
        }
        transaction {
            command(loanState.issuer.owningKey) { LoanContract.LoanCommands.Issue() }
            timeWindow(ZonedDateTime.of(LocalDate.now(), time, zoneId).toInstant())
            output { loanState } // Two outputs fails.
            output { dummyState}
            this `fails with` "Only a single output must be created when issugin a Loan"
        }

        transaction {
            command(loanState.issuer.owningKey) { LoanContract.LoanCommands.Issue() }
            output { loanState } // One output passes.
            timeWindow(ZonedDateTime.of(LocalDate.now(), time, zoneId).toInstant())
            this.verifies()
        }
    }
}

Notice that the second transaction fails correctly (when I remove the first), but the first give me this error

2017-08-14 12:32:15,250 main WARN Unable to instantiate org.fusesource.jansi.WindowsAnsiOutputStream

java.lang.AssertionError: Expected exception but didn't get one

at net.corda.testing.Verifies$DefaultImpls.failsWith(LedgerDSLInterpreter.kt:62)
at net.corda.testing.TransactionDSLInterpreter$DefaultImpls.failsWith(TransactionDSLInterpreter.kt)
at net.corda.testing.TestTransactionDSLInterpreter.failsWith(TestDSL.kt:89)
at net.corda.testing.Verifies$DefaultImpls.fails with(LedgerDSLInterpreter.kt:76)
at net.corda.testing.TransactionDSLInterpreter$DefaultImpls.fails with(TransactionDSLInterpreter.kt)
at net.corda.testing.TestTransactionDSLInterpreter.fails with(TestDSL.kt:89)
at net.corda.testing.TransactionDSL.fails with(TransactionDSLInterpreter.kt)
at com.template.contractTests.LoanContractIssueTest$issueTransactionMustHaveOneOutputOfTypeLoanContract$1$1.invoke(LoanContractIssueTest.kt:123)
at com.template.contractTests.

Why it isn't raising an exception? It looks like the tx.outputs.isNotEmpty() is not working.

Any help is appreciated

Upvotes: 0

Views: 170

Answers (2)

Joel
Joel

Reputation: 23140

The issue is that the transaction in the first test does not contain any inputs or outputs. For a transaction to be valid, it must be accepted by the contracts of all the inputs and outputs. Since you have no inputs or outputs, the transaction is always valid.

This is not an issue when you have two outputs, as the verify function is run due to the presence of the two outputs in that case.

Upvotes: 1

Mike Hearn
Mike Hearn

Reputation: 1473

Good question - from your code I don't see the issue. However, note that your rules seem overlapping. You test that there is exactly one output, and then after that, that there are >0 outputs. The second test can be removed, it will never catch anything that the first doesn't.

Upvotes: 1

Related Questions