How can I mock a fake database for when unit testi

2020-07-04 06:04发布

问题:

I've been using Knex successfully to connect to a backend database. But I want to be able to unit test my code. Is there a way to mock the database connection?

I've tried using proxyquire but I can't seem to get it to work.

The problem seems to be with the way Knex is initialized.

var knex = require('knex')({
  client: 'mysql',
  connection: {}
});

I setup knex to be mocked in my unit test.

myService = proxyquire('../app/myService', {
        'knex': knexProxy
});

My service includes knex.

var knex = require('knex').knex,

When my service runs a query, it fails.

var sql = knex("table_name");
sql.insert(rowToInsert, "auto_increment_id");
sql.then(function (insertId) {
    resolve();
}, function (err) {
    reject(err);
});

For some reason I just can't seem to capture the request before it attempts the connection.

I've also, tried to create a custom Knex Client, but that hasn't worked yet either.

回答1:

Using jest:

Create the file /__mocks__/knex.js in your app root:

module.exports = () => ({
  select: jest.fn().mockReturnThis(),
  from: jest.fn().mockReturnThis(),
  where: jest.fn().mockReturnThis(),
  first: jest.fn().mockReturnThis(),
  then: jest.fn(function (done) {
    done(null)
  })
})

Pass the desired return value to done



回答2:

I have been using in-memory Sqlite3 databases for automated testing with great success. It's not true unit testing however it does run much faster than MySQL or PostgreSQL. I have posted more details about this solution on a different question.



回答3:

I used jest to mock knex but I had to define an object that contains the method that I used. not the most elegant solution but is working

let knexMock = () => {
    const fn = () => {
        return {
            returning: function() {
                return {
                    insert: jest.fn().mockImplementation(() => [123123])
                }
            },
            insert: jest.fn()
        }
    }
    fn.raw = jest.fn()
    return fn
}

knex.mockImplementation(knexMock)