Testing your integration
Never touch the real key
Point PSEUDONYM_HOME to a new temporary folder before your tests call the library. Each folder gets its own key and directory. With node:test (any test runner works the same way):
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { beforeEach } from "node:test";
beforeEach(() => {
process.env.PSEUDONYM_HOME = mkdtempSync(path.join(tmpdir(), "pseudonym-"));
});
The library reads PSEUDONYM_HOME on every call, so setting it in beforeEach is enough. Child processes you spawn need it in their environment too.
Don't assert on fixed aliases
Each temporary folder has a new random key, so aliases change between runs. Assert on their shape, or compare two calls:
const ALIAS = /^A-[0-9A-HJKMNP-TV-Z]{6,12}$/;
const [a] = await remember([person]);
assert.match(a, ALIAS);
assert.equal(await remember(person), a); // stable within the same folder
Assert that nothing personal leaks
The most useful test of an integration: call your tools and check that no personal value from your fixtures appears in their output.
const personal = students.flatMap((s) => [s.fullName, s.email, s.studentNumber, String(s.id)]);
const output = await callTool("list_students");
for (const value of personal) assert.ok(!output.includes(value), `leaked: ${value}`);
Use invented data in fixtures: invented names, and domains such as example.test or example-school.test.
Test the way back
For write tools, check that an alias from one tool resolves to the right record, and that an unknown alias is a readable error:
const [{ student }] = JSON.parse(await callTool("list_students"));
await callTool("grade_student", { student, grade: 6 });
assert.equal(gradebook.get(students[0].id), 6);
const result = await callTool("grade_student", { student: "A-000000", grade: 5 });
assert.equal(result.isError, true);
The classroom example's test does all of this through MCP, with an in-process client.