Built-in matchers and helpers
Reference map for transaction predicates, map expectations, and out-action helpers in Acton tests
Before writing custom matchers, check the built-in ones first. Acton already ships a useful set of helpers for transaction search, map assertions, and out-action inspection.
Transaction search matchers
Use these functions to find or assert on transactions from net.send(...):
findTransaction()toHaveSuccessfulDeploy()toHaveSuccessfulTx()toHaveTx()toNotHaveTx()toHaveBouncedTx()toHaveFailedTx()
You can mix exact scalar matches and predicate functions inside SearchParams:
expect(res).toHaveTx({
from: fun (addr: address): bool {
return addr == deployer.address;
},
to: harness.address,
value: ton("0.5"),
opcode: 0x0000_0001,
});Important matcher semantics:
SearchParamsfields accept either exact values or predicate functions.toHaveSuccessfulTx()forcessuccess = trueand defaultsexitCode = 0unless overridden explicitly.toHaveFailedTx()requires a non-zeroexitCode.- Bounced-message opcode matching should be done with
toHaveBouncedTx()or an explicitbounced: truefilter. - Predicate functions can be useful for custom diagnostics, but runtime errors inside those predicates surface back to the test output.
Go deeper in:
External message matchers
net.sendExternal(...) returns an ExternalSendResult. When the external-in
message is accepted, result.transactions contains the produced transaction
trace. When the contract rejects the message before acceptance, the trace is
null and result.error contains emulator metadata such as
externalNotAccepted, message and vmExitCode.
val result = net.sendExternal(msg);
expect(result).toBeAccepted();
val txs = result.unwrap();
expect(txs).toHaveAllSuccessfulTxs();
val tx = result.at(0);
result.giveName("external vote");Available helpers:
isAccepted()returns whether the external-in message produced a trace.unwrap()returns the producedSendResultListor fails with the same external diagnostics astoBeAccepted().at(index)unwraps the trace and returns oneSendResult.giveName(name)names the external trace for the Test UI and gas/fee reports.waitForFirstTransaction()waits for the root on-chain transaction, or returnsnullwhen the external message was not accepted.waitForTrace()waits for the full on-chain trace, or returnsnullwhen the external message was not accepted.findExternalOutMessage<T>()searches external-out messages in the accepted trace, or returnsnullfor rejected external-in messages.
Available matchers:
toBeAccepted()expects an accepted external-in message and a produced trace.toBeNotAccepted()expects rejection before acceptance.toHaveExternalVmExitCode(exitCode)checks the VM exit code reported for a rejected external-in message. For accepted messages, use transaction matchers onresult.unwrap().
Failed toBeAccepted() checks include the external status, emulator reason, VM
exit code when available, known exit-code description or ABI error name, source
location, and full backtrace when the test is run with --backtrace full.
val result = net.sendExternal(invalidMsg);
expect(result).toBeNotAccepted();
expect(result).toHaveExternalVmExitCode(10);Rejected external-in diagnostics include the matcher location and, with
--backtrace full, the contract-side onExternalMessage backtrace.
Go deeper in:
Map expectations
Map helpers are useful for get-method results and in-memory fixtures:
val balances: map<int32, int32> = net.runGetMethod(ledger.address, "balances");
expect(balances).toContainKey(1);
expect(balances).toContainValue(20);
expect(balances).toNotContainKey(99);
expect(balances).toNotContainValue(777);
expect(balances).toBeNonEmpty();
expect(balances).toHaveLength(2);Available helpers:
toContainKey()toNotContainKey()toContainValue()toNotContainValue()toBeEmpty()toBeNonEmpty()toHaveLength()
Practical note:
toHaveLength()counts the current number of keys after overwrites, not the number ofset()calls used to build the map.
Go deeper in:
Out-action helpers
Use action helpers to inspect C5 output, planned sends, or action kinds:
val outActions = testing.outActions();
expect(outActions).toBeSendMessageAt<IncreaseCounter>(2);
val action = outActions.getSendMessageAt(2);
val body = outActions.getSendMessageBodyAt<IncreaseCounter>(2);The most useful entry points are:
testing.outActions()for the current VM out listSendResult.allOutActions()for one executed transaction resultOutMessage.outActions(mode)for a message before it is sentOutActionList.at()OutActionList.getSendMessageAt()OutActionList.getSendMessageBodyAt()Expectation<OutActionList>.toBeSendMessageAt()
Important out-action semantics:
- Out-action indexing is reversed: index
0is the last produced action. kind()returns stable string tags such as"send-message"and"reserve-currency".getSendMessageAt()andgetSendMessageBodyAt()returnnullwhen the selected action is not a send-message action.toBeSendMessageAt<Msg>()verifies that the action is a send-message action and that typed message loading succeeds. For body-field assertions, load the message or body separately.
Go deeper in:
When to write custom matchers
If the built-in helpers still do not match a domain-specific vocabulary, extend Expectation<T> with a custom matcher.
Last updated on