答案 0 :(得分:7)
假设我们有一个非常简单的服务,该服务通过id查找用户实体:
export class UserService {
constructor(@InjectRepository(UserEntity) private userRepository: Repository<UserEntity>) {
}
async findUser(userId: string): Promise<UserEntity> {
return this.userRepository.findOne(userId);
}
}
然后,您可以使用以下模拟工厂模拟UserRepository
(根据需要添加更多方法):
// @ts-ignore
export const repositoryMockFactory: () => MockType<Repository<any>> = jest.fn(() => ({
findOne: jest.fn(entity => entity),
// ...
}));
使用工厂可确保每次测试均使用新的模拟。
describe('UserService', () => {
let service: UserService;
let repositoryMock: MockType<Repository<UserEntity>>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UserService,
// Provide your mock instead of the actual repository
{ provide: getRepositoryToken(UserEntity), useFactory: repositoryMockFactory },
],
}).compile();
service = module.get<UserService>(UserService);
repositoryMock = module.get(getRepositoryToken(UserEntity));
});
it('should find a user', async () => {
const user = {name: 'Alni', id: '123'};
// Now you can control the return value of your mock's methods
repositoryMock.findOne.mockReturnValue(user);
expect(service.findUser(user.id)).toEqual(user);
// And make assertions on how often and with what params your mock's methods are called
expect(repositoryMock.findOne).toHaveBeenCalledWith(user.id);
});
});
出于类型安全性和舒适性的考虑,您可以对模拟使用以下类型(远非完美,当在接下来的主要版本中开玩笑本身开始使用Typescript时,可能会有更好的解决方案):
export type MockType<T> = {
[P in keyof T]: jest.Mock<{}>;
};
答案 1 :(得分:2)
我的解决方案使用sqlite内存数据库,我在其中插入所有需要的数据并在每次测试运行之前创建架构。因此,每个测试都使用相同的数据集,因此您不必模拟任何TypeORM方法:
import { Test, TestingModule } from "@nestjs/testing";
import { CompanyInfo } from '../../src/company-info/company-info.entity';
import { CompanyInfoService } from "../../src/company-info/company-info.service";
import { Repository, createConnection, getConnection, getRepository } from "typeorm";
import { getRepositoryToken } from "@nestjs/typeorm";
describe('CompanyInfoService', () => {
let service: CompanyInfoService;
let repository: Repository<CompanyInfo>;
let testingModule: TestingModule;
const testConnectionName = 'testConnection';
beforeEach(async () => {
testingModule = await Test.createTestingModule({
providers: [
CompanyInfoService,
{
provide: getRepositoryToken(CompanyInfo),
useClass: Repository,
},
],
}).compile();
let connection = await createConnection({
type: "sqlite",
database: ":memory:",
dropSchema: true,
entities: [CompanyInfo],
synchronize: true,
logging: false,
name: testConnectionName
});
repository = getRepository(CompanyInfo, testConnectionName);
service = new CompanyInfoService(repository);
return connection;
});
afterEach(async () => {
await getConnection(testConnectionName).close()
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should return company info for findOne', async () => {
// prepare data, insert them to be tested
const companyInfoData: CompanyInfo = {
id: 1,
};
await repository.insert(companyInfoData);
// test data retrieval itself
expect(await service.findOne()).toEqual(companyInfoData);
});
});
我在这里受到启发:https://gist.github.com/Ciantic/be6a8b8ca27ee15e2223f642b5e01549
答案 2 :(得分:2)
您也可以使用测试数据库并在那里插入数据。
describe('EmployeesService', () => {
let employeesService: EmployeesService;
let moduleRef: TestingModule;
beforeEach(async () => {
moduleRef = await Test.createTestingModule({
imports: [
TypeOrmModule.forFeature([Employee]),
TypeOrmModule.forRoot({
type: 'postgres',
host: 'db',
port: 5432,
username: 'postgres',
password: '',
database: 'test',
autoLoadEntities: true,
synchronize: true,
}),
],
providers: [EmployeesService],
}).compile();
employeesService = moduleRef.get<EmployeesService>(EmployeesService);
});
afterEach(async () => {
// Free DB connection for next test
await moduleRef.close();
});
describe('findOne', () => {
it('returns empty array', async () => {
expect(await employeesService.findAll()).toStrictEqual([]);
});
});
});
您需要手动创建数据库,例如psql -U postgres -c 'create database test;'
。架构同步将自动发生。
答案 3 :(得分:1)
我还发现这对我有用:
export const mockRepository = jest.fn(() => ({
metadata: {
columns: [],
relations: [],
},
}));
和
const module: TestingModule = await Test.createTestingModule({
providers: [{ provide: getRepositoryToken(Entity), useClass: mockRepository }],
}).compile();