如何用Sinon模拟pg Pool

问题描述 投票:2回答:2

[在先前的项目中,我用mysql library模拟了Sinon。我这样做是这样的:

X.js

const con = mysql.createPool(config.mysql);
...

Some other place in the project

const rows = await con.query(query, inserts);
...

X.test.js

const sinon = require('sinon');
const mockMysql = sinon.mock(require('mysql'));
...

mockMysql.expects('createPool').returns({
        query: () => {
            // Handles the query...
        },
...

效果很好。

[在另一个项目中,我尝试与Sinon一起模拟pg

pool.js

const { Pool } = require('pg');
const config = require('@blabla/config');
const pool = new Pool(config.get('database'));

module.exports = pool;

Some other place in the project

const con = await pool.connect();
const result = await con.query(...

Y.test.js

???

我不明白如何模拟connect().query()。以下方法均无效:

1:

const { Pool } = require('pg');
const config = require('@blabla/config');

const mockPool = sinon.mock(new Pool(config.get('database')));
...
mockPool.expects('connect').returns({
  query: () => {
    console.log('query here');
  },
});

1不会导致任何错误,但是使用了真正的数据库连接。

2:

const { Pool } = sinon.mock(require('pg'));
const config = require('@blabla/config');

const pool = new Pool(config.get('database'));

pool.expects('connect').returns({
  query: () => {
    console.log('query here');
  },
}); 

2 => TypeError: Pool is not a constructor

3:

const { Pool } = sinon.mock(require('pg'));
const config = require('@blabla/config');

const pool = sinon.createStubInstance(Pool);
pool.connect.returns({
  query: () => {
    console.log('query here');
  },
});

3 => TypeError: The constructor should be a function.

有人可以指出如何模拟PostgreSQL连接的正确方向吗?

javascript node.js sinon pg
2个回答
0
投票

由于您需要模拟查询的返回结果,所以我认为最简单的解决方案是从需要查询结果的代码中提取数据库。例如,您的查询结果正在返回有关某个人的信息。创建具有用于与数据库交互的特定方法的person.js模块。

您需要从数据库中获取个人信息的其他代码将不知道或不在乎您使用的是哪种类型的数据库,或者您如何连接到数据库,他们只想知道在需要时,person.js公开了哪些方法。

//person.js
const { Pool } = require('pg)
// do other database connection things here
const getPersonById = function (id) {
  // use your query here and return the results
}
module.exports = { getPersonById }

现在在您的测试中,您模拟的是person模块,而不是pg模块。想象一下,如果您有20个奇怪的测试都设置了模拟mysql池,那么您将其更改为pg,则必须更改其中的all噩梦。但是通过抽象化数据库连接类型/设置,它使测试变得更加容易,因为现在您只需要存根/模拟person.js模块即可。

const person = require('../person.js') //or whatever relative file path it's in
const sinon = require('sinon')

describe('person.js', function () {
 it('is stubbed right now', function () {
  const personStub = sinon.stub(person)
  personStub.getPersonById.returns('yup')

  expect(personStub.getPersonById()).to.eq('yup')
 })
})

0
投票

示例:我有这样的postgres.js。

const { Pool } = require('pg');

const handler = {
  count: async (pgQuery) => {
    try {
      const pool = new Pool();
      const res = await pool.query(pgQuery);
      return { count: parseInt(res.rows[0].counter, 10) };
    } catch (error) {
      // Log/Throw error here.
    }
    return false;
  }
}

module.exports = handler;

我在postgres.spec.js上创建的规范测试就是这样。

const { expect } = require('chai');
const sinon = require('sinon');
const pgPool = require('pg-pool');
const handler = require('postgres.js');

describe('Postgres', function () {
  it('should have method count that bla bla', async function () {
    // Create stub pgPool query.
    const postgreeStubQuery = sinon.stub(pgPool.prototype, 'query');
    postgreeStubQuery.onFirstCall().throws('XXX');
    postgreeStubQuery.onSecondCall().resolves({
      rows: [{ counter: 11 }],
    });

    // Catch case.
    const catcher = await handler.count('SELECT COUNT()..');
    expect(catcher).to.equal(false);
    expect(postgreeStubQuery.calledOnce).to.equal(true);

    // Correct case.
    const correct = await handler.count('SELECT COUNT()..');
    expect(correct).to.deep.equal({ count: 11 });
    expect(postgreeStubQuery.calledTwice).to.equal(true);

    // Restore stub.
    postgreeStubQuery.restore();
  });
});

要存根pool.query(),您需要存根pg-pool原型和方法查询。

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.