Build on Asentum
Testing Contracts
Fast feedback for builders · Estimated read time: 6 minutes
TL;DR
Two layers of tests get you where you need to be: in-process unit tests that run the VM directly (no network, millisecond feedback) and integration tests that deploy against a real chain (live testnet or a local node) via the SDK. Both layers use standard JavaScript test runners — Vitest, Jest, or Node's built-in runner.
Unit tests in-process
The @asentum/vm package exports a standalone VM. You can deploy, call methods, assert on state — all in memory, no network, no node.
import { test, expect } from 'vitest';
import { createVm } from '@asentum/vm';
test('counter increments', async () => {
const vm = createVm();
const c = await vm.deploy(`
function init() { storage.set('n', 0n); }
function inc() { storage.set('n', storage.get('n') + 1n); }
function get() { return storage.get('n'); }
`);
await c.call('init');
await c.call('inc');
await c.call('inc');
expect(await c.view('get')).toBe(2n);
});This is the right layer for logic tests, invariants, and gas sanity-checks. Fast, deterministic, zero dependencies.
Integration tests against testnet
For end-to-end confidence, deploy against the live testnet using the SDK. These are slower (2-second block time) but exercise the full pipeline — real Dilithium3 signing, real BFT consensus, real explorer receipts.
import { test } from 'vitest';
import { AsentumClient, AsentumWallet } from '@asentum/sdk';
import { readFileSync } from 'node:fs';
test('end-to-end counter', async () => {
const client = new AsentumClient('https://testnet.asentum.com');
const wallet = AsentumWallet.create(client);
await wallet.requestFaucet();
const source = readFileSync('./contracts/counter.js', 'utf8');
const c = await wallet.deploy(source);
await (await c.send('init')).wait();
await (await c.send('inc')).wait();
expect(await c.view('get')).toBe(1n);
}, { timeout: 30_000 });Using Vitest
Vitest is the recommended runner — fast, ESM-native, TypeScript out of the box. A minimal setup:
pnpm vitest
Jest works the same way — Asentum packages are pure ESM with no Jest-specific config needed.
Testing patterns
- Assert events. Every
sendreturns aSentTx;tx.wait()resolves to a receipt with aneventsarray. Assert on them for state-transition correctness. - Assert reverts. Wrap a failing call in
expect().rejects. The revert message comes back on the error. - Test access control. Instantiate multiple
AsentumWallets to simulate differentmsg.sendervalues. - Test cross-contract. Deploy two contracts in the same test; verify that
E(other).method()returns what you expect.
Running in CI
Unit tests are fine to run in CI unchanged — no network needed. For integration tests against the live testnet, use a funded CI wallet or drip from the faucet at the start of each run. Budget ~5 seconds per tx (2s block + latency). For heavy CI, consider running a local full node.
Read next