Can't mock/stub knex methods

42 views Asked by At

On my code I have something like:

const getItem = async (itemId) => {
  const item = await knex('item').where('id', itemId).first();

  console.log(item);
};

And on my test file:

sinon.stub(knex, 'first').resolves({ id: 1 });

knex is imported as const knex = require('Knex')(config).

I feel like knex('table_name') creates a different instance and methods are not being mocked.

UPDATE stub only works like this:

const knexStub = sinon.stub(knex, 'from').callsFake(() => ({
      where: () => ({
        first: () => null
      }),
      insert: () => sinon.fake()
    }));

then in my function like:

const getItem = async (itemId) => {
  const item = await knex.from('item').where('id', itemId).first();

  console.log(item);
};

I like it better as knex('table_name') but it looks like it's not possible.

1

There are 1 answers

1
Lin Du On BEST ANSWER

sinon doesn't support to stub standalone function, we need to use proxyquire package.

getItem.js:

const knex = require("knex")({
  client: "mysql",
  connection: {
    host: "127.0.0.1",
    port: 3306,
    user: "your_database_user",
    password: "your_database_password",
    database: "myapp_test",
  },
});

const getItem = async (itemId) => {
  return knex("item")
    .where("id", itemId)
    .first();
};

module.exports = getItem;

getItem.test.js:

const proxyquire = require("proxyquire");
const sinon = require("sinon");

describe("77622992", () => {
  it("should pass", async () => {
    const knexClient = sinon.stub().returns({
      where: sinon.stub().returnsThis(),
      first: sinon.stub().resolves({ id: 1 }),
    });
    const knexStub = sinon.stub().returns(knexClient);
    const getItem = proxyquire("./getItem", {
      knex: knexStub,
    });
    const r = await getItem(1);
    sinon.assert.match(r, { id: 1 });
  });
});