CodingNeed.

3 · Reliability and delivery · 45 MIN

Project · Test a service contract

Test externally observable behavior rather than implementation details.

The built-in test runner provides assertions without requiring a framework dependency. Keep the calculation in a separate module so tests can call it without starting an HTTP listener. These tests cover ordinary input, an empty collection and rejected data. They also make the chosen negative-amount policy visible. Expand toward an HTTP integration test only when HTTP behavior is part of the feature. Avoid writing assertions that merely repeat each line of the implementation instead of checking meaningful outcomes and failure guarantees.

Verify a failed record never yields a partial success result.

Read the example

// totals.mjs
export function total(rows){
  return rows.reduce((sum,row)=>{
    if(!Number.isSafeInteger(row.amount)||row.amount<0)throw new Error('invalid amount');
    const next=sum+row.amount;if(!Number.isSafeInteger(next))throw new Error('overflow');return next;
  },0);
}
// totals.test.mjs (separate file; run node --test)
import test from 'node:test';
import assert from 'node:assert/strict';
import {total} from './totals.mjs';
test('totals valid rows',()=>assert.equal(total([{amount:5},{amount:7}]),12));
test('empty report',()=>assert.equal(total([]),0));
test('rejects negative',()=>assert.throws(()=>total([{amount:-1}]),/invalid/));
Check the expected output
node --test reports three passing tests when files are saved separately.

Your challenge

Add overflow and immutability tests, then connect this function to a bounded, validated HTTP endpoint in the Expense API project.

Solution cost: O(n) total calculation. time · O(1) accumulator beyond input and test data. space

Common trap

A passing happy-path test does not establish input validation or safe failure behavior.

Study the project implementation
// totals.mjs
export function total(rows){
  return rows.reduce((sum,row)=>{
    if(!Number.isSafeInteger(row.amount)||row.amount<0)throw new Error('invalid amount');
    const next=sum+row.amount;if(!Number.isSafeInteger(next))throw new Error('overflow');return next;
  },0);
}
// totals.test.mjs (separate file; run node --test)
import test from 'node:test';
import assert from 'node:assert/strict';
import {total} from './totals.mjs';
test('totals valid rows',()=>assert.equal(total([{amount:5},{amount:7}]),12));
test('empty report',()=>assert.equal(total([]),0));
test('rejects negative',()=>assert.throws(()=>total([{amount:-1}]),/invalid/));

Further reading: Official documentation

Essential cookies keep your account signed in. Optional analytics is not configured on this site. Your choice does not affect access to lessons.

Read the Privacy Policy. You can change this choice in the footer.