使用Jest测试第三方模块内的匿名功能



我有一个非常简单的模块,它使用pg(node-postgrelib(模块, 我想实现一个 Jest 测试,在模拟pg模块时,我想运行它的回调函数以查看console.log运行并且我的回调被调用

我嘲笑了该模块并试图监视和替换"查询"方法,但它失败并粉碎了, 知道我做错了什么吗?

测试对象:

import {Pool} from 'pg';
const pool = new Pool();
module.exports = {
query: (text, params, callback) => {
const start = Date.now();
return pool.query(text, params, (err, res) => {
const duration = Date.now() - start;
console.log('executed query', {text, duration, rows: res.rowCount});
callback(err, res);
});
}
};

测试:

jest.mock('pg');
import module from './index';
import { Pool } from 'pg'
beforeAll(() => {
Pool.mockImplementation(()=>{return jest.fn()});
});

it('callback is called', () => {
const cb = (err, res) => true;
const query = jest.spyOn(Pool, "query");         // <---- Not right, Error
query.mockImplementation((a,b,c) => c({},{}));
const resolve = module.query('QUERY TEXT', { a: 1, b: 2}, cb);
resolve();                                       // <---- Not what I expect
expect(cb).toBeCalled();
});
});

抛出错误: 错误:无法监视查询属性,因为它不是函数;未定义给定

20 |   it('callback is called', () => {
21 |     const cb = (err, res) => true;
> 22 |     const query = jest.spyOn(Pool, "query");
|                        ^
23 |     query.mockImplementation((a,b,c) => c({},{}));
24 |     const resolve = module.query('QUERY TEXT', { a: 1, b: 2}, cb);
25 |     resolve();
at ModuleMockerClass.spyOn (node_modules/jest-mock/build/index.js:697:15)
at Object.spyOn (src/db/index.test.js:22:24)

谢谢

下面是单元测试解决方案:

index.js

import { Pool } from 'pg';
const pool = new Pool();
module.exports = {
query: (text, params, callback) => {
const start = Date.now();
return pool.query(text, params, (err, res) => {
const duration = Date.now() - start;
console.log('executed query', { text, duration, rows: res.rowCount });
callback(err, res);
});
}
};

index.spec.js

import mod from '.';
import { Pool } from 'pg';
jest.mock('pg', () => {
const mPool = {
query: jest.fn()
};
return { Pool: jest.fn(() => mPool) };
});
const pool = new Pool();
afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});
it('callback is called', done => {
let queryCallback;
pool.query.mockImplementation((text, params, callback) => {
queryCallback = callback;
});
const logSpy = jest.spyOn(console, 'log');
const userCallback = jest.fn();
mod.query('text', 'params', userCallback);
const mRes = { rowCount: 1 };
queryCallback(null, mRes);
expect(pool.query).toBeCalledWith('text', 'params', queryCallback);
expect(userCallback).toBeCalledWith(null, mRes);
expect(logSpy).toBeCalledWith('executed query', { text: 'text', duration: expect.any(Number), rows: 1 });
done();
});

100% 覆盖率的单元测试结果:

PASS  src/stackoverflow/52831401/index.spec.js
✓ callback is called (15ms)
console.log node_modules/jest-mock/build/index.js:860
executed query { text: 'text', duration: 0, rows: 1 }
----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.026s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52831401

最新更新