This page is also available in Italiano.

Continua in italiano

Testing

TinyDI has no test-specific API, and does not need one. Registration and resolution are ordinary method calls, so testing looks like ordinary TypeScript: build a container, register a fake instead of the real implementation, resolve, assert.

A fresh container per test

A Singleton's cached instance lives on the Container it was built from, not in a global. Creating a new Container in each test's setup is enough to guarantee no state leaks between tests — there is no reset() step to remember.

ts
import { Container, createToken } from 'tinydi-container';
 
interface IMailService {
  send(to: string, body: string): Promise<void>;
}
 
const MailServiceToken = createToken<IMailService>('MailService');
 
class FakeMailService implements IMailService {
  sent: { to: string; body: string }[] = [];
  async send(to: string, body: string): Promise<void> {
    this.sent.push({ to, body });
  }
}
 
let container: Container;
let mail: FakeMailService;
 
beforeEach(() => {
  container = new Container();
  mail = new FakeMailService();
  container.registerInstance(MailServiceToken, mail);
});
 
test('sends a welcome email on signup', async () => {
  await onSignup(container, 'user@example.com');
  expect(mail.sent).toHaveLength(1);
});

No mocking library needed

A fake is just a plain class or object implementing the same interface — TypeScript checks it structurally at compile time, exactly like the real implementation. There is nothing to import beyond tinydi-container itself.

Swapping a fake mid-test

remove() exists specifically for this: registering an already-registered token throws RegistrationError, on purpose, so call remove() first before re-registering it with a different fake.

ts
// Later in the same test file, a different test needs the real
// implementation to fail so it can assert on the error path:
container.remove(MailServiceToken);
container.registerInstance(MailServiceToken, new FailingMailService());

What this does not cover

TinyDI does not provide spies, call-count assertions, or automatic mock generation. Pair it with your test runner's own assertion library (Vitest's expect, Jest's expect, or similar) for that — a fake registered via registerInstance is a plain object, so any assertion library works against it unchanged.

to navigate to select Esc to close