一键导入
angular-unit-testing
Best practices for Angular unit testing with Jest in the blueprint frontend. Use this when writing or reviewing Angular/TypeScript spec files.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Best practices for Angular unit testing with Jest in the blueprint frontend. Use this when writing or reviewing Angular/TypeScript spec files.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Enigmatry Entry Blueprint .NET 9 Web API patterns covering MediatR, Autofac, FluentValidation, and vertical slice architecture. Use this when adding or modifying .NET API features, handlers, validators, or controllers.
Best practices for Azure DevOps Pipeline YAML files in the Enigmatry Entry Blueprint project. Use this when creating, editing, or reviewing Azure DevOps CI/CD pipeline YAML.
Enigmatry Entry Blueprint code review checklist covering .NET 9 and Angular/TypeScript. Use this when reviewing or performing a code review on blueprint changes.
C# 13 coding standards for the YOS project — naming, formatting, nullability, and testing conventions. Use this when writing, reviewing, or refactoring any C# (.cs) file.
Best practices for C# unit and integration testing with NUnit, FluentAssertions and NSubstitute. Use this when writing or reviewing C# tests.
TypeScript 5.x / ES2022 coding standards for the YOS Angular project — naming, formatting, type system, async patterns, and architecture conventions. Use this when writing, reviewing, or refactoring any TypeScript (.ts) file.
| name | angular-unit-testing |
| description | Best practices for Angular unit testing with Jest in the blueprint frontend. Use this when writing or reviewing Angular/TypeScript spec files. |
npm test, npm run test:ci).jest-preset-angular; the setup file is src/testing/setup.ts.describe, it, expect, jest, beforeEach, etc.) are available without imports — do not import them; they are injected automatically.foo.service.spec.ts alongside foo.service.ts.src/app/**/*.spec.ts.import { TestBed } from '@angular/core/testing';
import { MyService } from './my.service';
import { SomeDependency } from './some.dependency';
const buildMocks = () => ({
someDependency: { getData: jest.fn().mockReturnValue(of('result')) } as unknown as SomeDependency
});
let service: MyService;
let mocks: ReturnType<typeof buildMocks>;
beforeEach(() => {
mocks = buildMocks();
TestBed.configureTestingModule({
providers: [
MyService,
{ provide: SomeDependency, useValue: mocks.someDependency }
]
});
service = TestBed.inject(MyService);
});
describe('MyService', () => {
describe('myMethod', () => {
it('should return expected result', () => { /* ... */ });
});
});
TestBed.configureTestingModule in beforeEach — Angular resets TestBed between tests automatically.buildMocks() factory in beforeEach — never share mutable mock state across tests.Use jest.mock(...) at the top of the file, then override behaviour in beforeEach:
jest.mock('./auth.service');
jest.mock('../services/current-user.service');
const loginMock = jest.fn().mockReturnValue(Promise.resolve());
const mockServicesWith = (user: UserProfile | null) => {
mockClass(AuthService, () => Object({
isAuthenticated: () => user !== undefined,
loginRedirect: loginMock
}));
};
beforeEach(() => {
loginMock.mockClear();
TestBed.configureTestingModule({ providers: [AuthService] });
});
Use the mockClass helper from @test/mocks/class-mocker to configure mock constructors:
import { mockClass } from '@test/mocks/class-mocker';
mockClass(CurrentUserService, () => Object({ currentUser: () => user }));
For interceptor tests, use AngularTesterBuilder from @test/builders/angular-tester-builder:
import { AngularTester, AngularTesterBuilder } from '@test/builders/angular-tester-builder';
let tester: AngularTester;
beforeEach(async() => {
tester = await new AngularTesterBuilder()
.withProviders([
provideHttpClient(withInterceptors([myInterceptor])),
provideHttpClientTesting(),
{ provide: MyService, useFactory: mockMyService }
])
.build();
});
it('should add header to API requests', (done: jest.DoneCallback) => {
tester.requestSuccess(done, (result: TestRequest) => {
expect(result.request.headers.get('X-Custom')).toEqual('value');
});
});
Always scan for duplication before writing a new it(). If multiple tests share the same body and differ only in input values, collapse them with describe.each or it.each:
// ❌ avoid — identical structure, only data differs
it('should forbid null user', () => { ... });
it('should forbid user without permission', () => { ... });
it('should allow user with permission', () => { ... });
// ✅ correct — one parameterized block
describe.each([
{ description: 'should forbid null user', user: null, allowed: false },
{ description: 'should forbid user without permission', user: userWithoutPerm, allowed: false },
{ description: 'should allow user with permission', user: userWithPerm, allowed: true }
])('PermissionService', ({ description, user, allowed }) => {
it(description, () => {
const service = arrangeWith(user);
expect(service.hasPermissions([PermissionId.ProductsWrite])).toBe(allowed);
});
});
await async service calls; never use void or fire-and-forget in tests.(done: jest.DoneCallback) for callback-style async (e.g. HTTP mock assertions):it('should resolve with data', async() => {
await expect(service.loadData()).resolves.toEqual({ id: 1 });
});
For utilities and pure functions, skip TestBed entirely:
import { myUtil } from './my-util';
describe('myUtil', () => {
it('should transform input correctly', () => {
const result = myUtil('input');
expect(result).toBe('expected');
});
});
npm run test:ci to generate coverage.src/app/core/**, src/app/shared/models/**, src/app/shared/pipes/**, src/app/shared/services/**, src/app/shared/validators/**.describe, it, expect, or jest from any module — they are global.jest-preset-angular..subscribe() in tests — use firstValueFrom() or pass of(value) directly.beforeEach.console.error unchecked; if a code path logs an error, assert jest.spyOn(console, 'error') was called.