Skip to content

The double that drifted

All labs

Two implementations of the same interface: a real one and an in-memory fake used in tests. A double is a claim about how the real thing behaves, and nothing checks that claim — unless you write a contract test, which is one suite run against both. Both are exported here, so you can do exactly that.

goalWrite one suite that passes against both implementations — and would fail if either changed.

The module

export function createStore() {
  const rows = new Map();
  return {
    put(key, value) {
      if (typeof key !== "string" || key.length === 0) {
        throw new Error("key must be a non-empty string");
      }
      rows.set(key, value);
      return value;
    },
    get(key) {
      return rows.has(key) ? rows.get(key) : null;
    },
    remove(key) {
      return rows.delete(key);
    },
    keys() {
      return [...rows.keys()].sort();
    },
  };
}

export function createFakeStore() {
  const rows = {};
  return {
    put(key, value) {
      if (typeof key !== "string" || key.length === 0) {
        throw new Error("key must be a non-empty string");
      }
      rows[key] = value;
      return value;
    },
    get(key) {
      return key in rows ? rows[key] : null;
    },
    remove(key) {
      if (!(key in rows)) {
        return false;
      }
      delete rows[key];
      return true;
    },
    keys() {
      return Object.keys(rows).sort();
    },
  };
}

Your tests

Mutants

Run the suite to see the board.