我正在为一个使用 Typeorm 而不使用 Nestjs 的项目创建单元测试。我正在为其创建单元测试的文件使用 queryRunner 来启动事务。我的问题是,我无法模拟数据源。我尝试了多种方法,但从未调用模拟来替换可以访问 postgresql 数据库的实际数据源。我看到了一些模拟它的解决方案,但它们都使用 Nestjs,我在我的例子中没有使用它。
我现在在测试中遇到的错误是:
Received promise rejected instead of resolved
Rejected to value: [TypeORMError: Driver not Connected]
任何帮助将不胜感激,因为我不是单元测试方面的专家。
这是我遇到问题的代码示例(替换了一些名称):
datasource.ts
//database config is defined in this file
export const datasource: DataSource = new DataSource(some_config);
dummy.service.ts
export const dummyService = () => {
//datasource is imported from the above file
const queryRunner = datasource.createQueryRunner();
await queryRunner.startTransaction();
try {
const foundObject = await queryRunner.manager.getRepository(MyObject).findOne({
where: { id: someId },
lock: { mode: 'pessimistic_write' },
});
//some more database calls
} catch (error) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
}
mock.datasource.ts
import { DataSource } from 'typeorm';
export const dataSourceMockFactory: () => MockType<DataSource> = jest.fn(
() => ({
createQueryRunner: jest.fn().mockImplementation(() => ({
connect: jest.fn(),
startTransaction: jest.fn(),
release: jest.fn(),
rollbackTransaction: jest.fn(),
manager: {
getRepository: jest.fn().mockImplementation(() => ({
create: jest.fn(),
findOne: jest.fn(() => {
return getMyDummyObject();
}),
})),
save: jest.fn(),
},
})),
}),
);
export type MockType<T> = {
// eslint-disable-next-line @typescript-eslint/ban-types
[P in keyof T]?: jest.Mock<{}>;
};
dummy.unit.test.ts
describe('dummy service test', () => {
let dataSourceMock: MockType<Typeorm.DataSource>;
beforeEach(async () => {
// This method did not work
jest.mock('typeorm', () => {
const actual = jest.requireActual('typeorm');
return {
...actual,
DataSource: dataSourceMockFactory(),
};
});
// The below method did not work either
jest.mock('./../../db/datasource', () => ({
datasource: dataSourceMockFactory(),
}));
});
afterEach(() => {
jest.clearAllMocks();
});
it('should test dummy service with transaction', async () => {
// getting an error here
await expect(
dummyFunction(),
).resolves.not.toThrow();
});
});
您可以使用内存中的sqlite数据库:
const options: ConnectionOptions = {
type: "sqlite",
database: "memory",
entities: [ User, Message ],
logging: true
}
用它来调用 createConnection,并在测试中使用该连接
快速,比模拟更好,并且对于单元测试来说“足够相似”。不过,仍然需要对 postgres 进行集成测试。
如果您依赖于数据库特定的功能,还有像 pg-mem 这样的东西: