test: harden business boundary conditions

This commit is contained in:
2026-07-15 00:03:55 +08:00
parent 17a5046ea0
commit b1f35f9d1a
65 changed files with 2311 additions and 293 deletions

View File

@@ -0,0 +1,43 @@
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { StudentsService } from './students.service';
function createService(repo: Record<string, jest.Mock>, organizationRepo = {}) {
return new StudentsService(
repo as never,
{} as never,
{} as never,
{} as never,
{} as never,
organizationRepo as never,
);
}
describe('StudentsService — archive lifecycle boundaries', () => {
it('rejects archiving an already archived student', async () => {
const repo = { findOne: jest.fn().mockResolvedValue({ id: 1, status: 'archived' }) };
await expect(createService(repo).remove(1)).rejects.toBeInstanceOf(BadRequestException);
});
it('rejects restoring a student that is not archived', async () => {
const repo = { findOne: jest.fn().mockResolvedValue({ id: 1, status: 'active' }) };
await expect(createService(repo).restore(1)).rejects.toBeInstanceOf(BadRequestException);
});
it('rejects an empty batch archive', async () => {
await expect(createService({}).batchRemove([])).rejects.toBeInstanceOf(BadRequestException);
});
it('rejects creating a student under a missing or archived organization', async () => {
const repo = { create: jest.fn(), save: jest.fn() };
const organizationRepo = { findOne: jest.fn().mockResolvedValue(null) };
await expect(
createService(repo, organizationRepo).create({ name: '张三', organizationId: 9 }),
).rejects.toBeInstanceOf(BadRequestException);
expect(repo.save).not.toHaveBeenCalled();
});
it('returns not found for a missing student', async () => {
const repo = { findOne: jest.fn().mockResolvedValue(null) };
await expect(createService(repo).findOne(404)).rejects.toBeInstanceOf(NotFoundException);
});
});