提问人:Florat 提问时间:10/19/2023 更新时间:11/8/2023 访问量:35
如何在 vitest 中模拟 node-postgres
How to mock node-postgres in vitest
问:
我试图用 esm 来嘲笑。但我遇到了不同的问题。
当我在函数中使用该类时:node-postgres
Pool
import {Pool} from 'pg';
...
const pool = new Pool({connectionString});
const client = await pool.connect();
await client.query('BEGIN');
...
当我如上所述导入时,我可以用以下命令模拟池:Pool
import {Pool} from 'pg'
vi.mock('pg', () => {
const Pool = vi.fn();
const Client = vi.fn();
return {Pool, Client};
});
function queryMockImplementation(migrationTableExists: boolean, migratedFiles?: string[]) {
return (queryString: string) => {
if (queryString === `SELECT EXISTS (SELECT FROM pg_tables WHERE schemaname = 'administration' AND tablename = 'migrations')`) {
return Promise.resolve({rows: [{exists: migrationTableExists}]});
}
return Promise.resolve({rows: []});
}
}
function connectMockImplementation(clientQueries: string[], throwOnSqlQuery?: string) {
return async() => {
return {
query: vi.fn().mockImplementation((queryString: string) => {
if (throwOnSqlQuery === queryString) {
throw new Error('Error thrown by mock for client query.');
}
clientQueries.push(queryString);
}),
release: vi.fn(),
};
};
}
然后在测试中,我可以进行以下操作:
it('Should mock', () => async {
const {Pool} = await import('pg');
const clientQueries: string[] = [];
Pool.prototype.query = vi.fn().mockImplementation(queryMockImplementation(false));
Pool.prototype.connect = vi.fn().mockImplementation(connectMockImplementation(clientQueries));
const pool = new Pool();
}
但这不是预期的方式。它有效,但我必须将数组注入到模拟实现中,以便客户端观察用 .我找不到直接嘲笑客户的方法。此外,这种导入方式在使用该库的包中也会产生 esm 问题。因此,当我尝试访问时:clientQueries
client.query
Pool
Pool
import pg from 'pg';
const {Pool} = pg;
我得到最生动的错误:
Error: [vitest] No "default" export is defined on the "pg" mock. Did you forget to return it from "vi.mock"?
If you need to partially mock a module, you can use "vi.importActual" inside:
vi.mock("pg", async () => {
const actual = await vi.importActual("pg")
return {
...actual,
// your mocked methods
},
})
所以我正在调整模拟:
vi.mock('pg', async () => {
const actual = <Record<string, any>>await vi.importActual("pg")
const Pool = vi.fn();
const Client = vi.fn();
return {...actual, Pool, Client};
});
但现在我还有另外两个问题。我必须在测试中提供实际的数据库和连接字符串,并且客户端查询模拟不再起作用。
答:
0赞
Florat
11/8/2023
#1
我解决了这个问题。vitest-allowSyntheticDefaultImports 的示例存储库
import {describe, vi, it, expect} from 'vitest';
import {connect} from './index';
import pg from 'pg';
const {Pool} = pg;
vi.mock('pg', async () => {
const actual = <Record<string, unknown>>await vi.importActual('pg');
return {
...actual,
default: {
Pool: vi.fn(),
}
};
});
describe('connect', () => {
it('should call Pool', () => {
connect('postgres://...');
expect(Pool).toBeCalledTimes(1);
});
});
评论