Skip to content

Testing ​

Accord code is easy to test because everything returns values. You have three levels.

1. Unit test an aggregate directly ​

No runtime needed. Create an instance, call a method, check the state and events.

ts
import { test } from 'node:test'
import assert from 'node:assert/strict'
import { Account } from './domain.ts'

test('deposit adds to the balance', () => {
  const account = Account.create({ status: 'OPEN', balance: 100 }, { rules: { maximum: 1_000 } })

  const [reply, error] = account.deposit(50)

  assert.equal(error, null)
  assert.deepEqual(reply, { balance: 150 })
  assert.deepEqual(account.getState(), { status: 'OPEN', balance: 150 })
  assert.deepEqual(account.pullEvents(), [{ _tag: 'Deposited', amount: 50, balance: 150 }])
})

Use Account.restore(state) for class aggregates.

2. Run a story ​

story() wires a fresh in-memory runtime and turns failed assertions into Unexpected.

ts
test('deposit through the runtime', async () => {
  const [, error] = await story(
    Bank,
    async (t) => {
      const [, openError] = await t.bank.account.open('a-1')
      if (openError !== null) return fail(openError)

      const [receipt, depositError] = await t.bank.account.deposit('a-1', 100)
      if (depositError !== null) return fail(depositError)

      const [summary] = await t.bank.summary.get('a-1', { atLeast: receipt })
      t.equal(summary, { balance: 100 })
      return ok(undefined)
    },
    { services: { rules: { maximum: 1_000 } } }
  )

  assert.equal(error, null)
})

3. Fake external systems ​

Services are plain values, so pass a fake through wire():

ts
const sent: unknown[] = []
const bank = wire(Bank, {
  services: {
    notifications: {
      send: async (message) => {
        sent.push(message)
        return ok(undefined)
      },
    },
  },
})

For HTTP, give client() a custom fetch that calls your serve() handler directly. No server needed.

Run tests ​

Accord itself uses Node's built-in test runner:

sh
node --test

Accord is currently UNLICENSED. No open-source license has been selected yet.