بنقرة واحدة
nest-unit-test
Guidelines for writing unit tests in this NestJS project
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Guidelines for writing unit tests in this NestJS project
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | nest-unit-test |
| description | Guidelines for writing unit tests in this NestJS project |
vitest-mock-extended — mock() and Mocked<T> are globals (declared in test.d.ts, set up in vitest.setup.ts). Do not import them.@nestjs/testing Test.createTestingModule + .useMocker(() => mock())@nestjs/typeorm — get mocked repos via module.get(getRepositoryToken(Entity))toBeDefined() for every dependency — one top-level sanity check is enoughAlways use .useMocker(() => mock()) so every dependency is auto-mocked. Only override when a specific mock behaviour is needed.
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { MyEntity } from './entities/my.entity';
import { MyService } from './my.service';
// `mock` and `Mocked<T>` are globals — no import needed
describe('MyService', () => {
let service: MyService;
let repo: Mocked<Repository<MyEntity>>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MyService],
})
.useMocker(() => mock())
.compile();
service = module.get(MyService);
repo = module.get(getRepositoryToken(MyEntity));
});
Extract repetitive object construction into factory helpers co-located in the spec file (or a shared test/factories/ file for cross-spec reuse). Factories accept partial overrides so each test only declares what is relevant.
// --- factories (top of spec file, or imported from test/factories/) ---
function createRemoteServer(
overrides: Partial<RemoteServer> = {}
): RemoteServer {
return {
id: "server-1",
name: "prod-db",
description: "Production database",
ownerId: "user-1",
...overrides,
};
}
function createRemoteServerDto(
overrides: Partial<CreateRemoteServerDto> = {}
): CreateRemoteServerDto {
return {
name: "prod-db",
description: "Production database",
...overrides,
};
}
Use them in tests:
it("should create a remote server", async () => {
const dto = createRemoteServerDto({ name: "staging-db" });
await service.create(dto, "user-1");
expect(repo.save).toHaveBeenCalledWith({ ...dto, ownerId: "user-1" });
});
Test thrown errors by asserting on rejects:
it("should throw when server not found", async () => {
repo.findOneOrFail.mockRejectedValue(
new EntityNotFoundError(RemoteServer, {})
);
await expect(service.findOne("missing")).rejects.toThrow(EntityNotFoundError);
});
Group by method using nested describe blocks. Name tests as plain English sentences that describe the observable outcome, not the implementation.
describe('MyService')
it('should be defined') ← single sanity check
describe('create')
it('should persist the entity with the caller's ownerId')
it('should throw ConflictException when name already exists')
describe('findOne')
it('should return the matching entity')
it('should propagate the repository error when not found')
| Anti-pattern | Why |
|---|---|
expect(x).toBeDefined() on every dep | TypeScript already guarantees types |
Testing method existence (toBeDefined on a function) | The compiler enforces this |
Duplicated literal objects in every it | Use factories |
any casts to satisfy mocks | Fix the mock type instead |
Testing that repo.save was called 1 time when only one call is possible | Prefer asserting what it was called with |