Как я могу смоделировать фальшивую базу данных при модульном тестировании против Knex?

Я успешно использовал Knex для подключения к серверной базе данных. Но я хочу иметь возможность тестировать свой код. Есть ли способ издеваться над подключением к базе данных?

Я пытался использовать proxyquire, но не могу заставить его работать.

Проблема, похоже, связана с тем, как инициализируется Knex.

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

Я настроил knex для издевательств в своем модульном тесте.

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

Мой сервис включает knex.

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

Когда мой сервис выполняет запрос, он терпит неудачу.

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

По какой-то причине я просто не могу перехватить запрос до того, как он попытается установить соединение.

Я также пытался создать пользовательский клиент Knex, но это тоже пока не сработало.


person Trevor Allred    schedule 27.01.2015    source источник
comment
Вы нашли какое-либо решение для этого? Я работаю с Knex, и у меня такая же проблема. Спасибо   -  person jomaora    schedule 20.04.2016


Ответы (5)


Используя шутку:

Создайте файл /__mocks__/knex.js в корне вашего приложения:

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)
  })
})

Передайте желаемое возвращаемое значение done

person Eduardo    schedule 10.04.2019
comment
У меня проблемы с отслеживанием. Не могли бы вы добавить пример использования этого макета? - person Richard; 02.11.2020

Я с большим успехом использую базы данных Sqlite3 в памяти для автоматизированного тестирования. Это не настоящее модульное тестирование, однако оно работает намного быстрее, чем MySQL или PostgreSQL. Я опубликовал более подробную информацию об этом решении по другому вопросу.

person Steven Hunt    schedule 23.09.2015

Я использую jest, и вы можете сделать что-то вроде этого:

   jest.mock('knex', () => {
        const fn = () => {
            return {
                select: jest.fn().mockReturnThis(),
                from: jest.fn().mockReturnThis(),
                where: jest.fn().mockReturnThis(),
                first: jest.fn().mockReturnThis(),
                insert: jest.fn().mockReturnThis(),
                raw: jest.fn().mockReturnThis(),
                then: jest.fn(function (done) {
                  done(null)
                })
                
            }
        }
        return fn
    })
person Andhika Maheva Wicaksono    schedule 25.08.2020

Я использовал jest для имитации knex, но мне пришлось определить объект, содержащий метод, который я использовал. не самое элегантное решение, но работает

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)
person OhadBasan    schedule 09.10.2018
comment
После возни с sinon и proxyquire это сработало для меня. Спасибо. - person WhyAyala; 01.12.2018

Я написал эту крошечную библиотеку под названием knex-mock-client, которая делает именно это, она позволяет вам настройте соединение с базой данных с помощью mockClient, который будет отслеживать ваши звонки и помогать вам с ответами.

Например:

// my-cool-controller.ts

import { db } from '../common/db-setup';

export async function addUser(user: User): Promise<{ id }> {
  const [insertId] = await db.insert(user).into('users');

  return { id: insertId };
}
// my-cool-controller.spec.ts
import { expect } from '@jest/globals';
import knex, { Knex } from 'knex';
import { getTracker, MockClient } from 'knex-mock-client';
import faker from 'faker';

jest.mock('../common/db-setup', () => {
  return knex({ client: MockClient });
});

describe('my-cool-controller tests', () => {
  let tracker: Tracker;

  beforeAll(() => {
    tracker = getTracker();
  });

  afterEach(() => {
    tracker.reset();
  });

  it('should add new user', async () => {
    const insertId = faker.datatype.number();
    tracker.on.insert('users').response([insertId]);
    const newUser = { name: 'foo bar', email: '[email protected]' };
    const data = await addUser(newUser);

    expect(data.id).toEqual(insertId);

    const insertHistory = tracker.history.insert;

    expect(insertHistory).toHaveLength(1);
    expect(insertHistory[0].method).toEqual('insert');
    expect(insertHistory[0].bindings).toEqual([newUser.name, newUser.email]);
  });
});
person felixmosh    schedule 16.05.2021