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

时间:2018-10-16 08:44:52

标签: javascript unit-testing jestjs node-pg-pool

我有一个非常简单的模块,它使用pg(node-postgre lib)模块, 我想实现一个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)

谢谢

1 个答案:

答案 0 :(得分:0)

这是单元测试解决方案:

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