Asentum

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 add -D vitest @asentum/vm @asentum/sdk
pnpm vitest

Jest works the same way — Asentum packages are pure ESM with no Jest-specific config needed.

Testing patterns

  • Assert events. Every send returns a SentTx; tx.wait() resolves to a receipt with an events array. 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 different msg.sender values.
  • 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