При использовании транзакций Knex я хотел смоделировать и протестировать его. У моего файла была такая структура:
const insert = async (entity, fastify) => { return fastify.knex.transaction(async trx => { try{ // ... const [entityId] = await fastify .knex("entity") .insert(entity) .returning("id"); // ... const anotherResult = await someRepository.findResult( entityId, trx ); // ... await anotherRepository.insert( entity, trx ); // ... return trx.commit(response); } catch (error) { logger.error(); await trx.rollback(error); } }); };
Моя проблема заключалась в насмешке над всем этим, чтобы это имело смысл, и я мог оправдать ожидания для всех используемых функций Knex.
Используя эти два имита, мы можем протестировать и проверить все методы Knex.
const mockKnex = async fastify => { fastify.knex = jest.fn().mockReturnThis(); fastify.transacting = jest.fn().mockReturnThis(); fastify.update = jest.fn().mockReturnThis(); fastify.insert = jest.fn().mockReturnThis(); fastify.select = jest.fn().mockReturnThis() fastify.from = jest.fn().mockReturnThis(); fastify.where = jest.fn().mockReturnThis(); fastify.knex.transaction = jest.fn(async function mockTransaction(cb) { return cb(trx); }); }; const trx = { commit: jest.fn(function(data) { return data; }), rollback: jest.fn(), };
Интересные факты об этом тестовом дублере:
Мы должны зарегистрировать этот «макет» перед тестированием, например:
const Fastify = require("fastify"); ... let fastify; beforeEach(() => { fastify = Fastify(); mockKnex(fastify); });
Тогда у нас могут быть ожидания от наших тестов:
expect(fastify.insert).toHaveBeenCalledWith(...); ... expect(trx.commit).toHaveBeenCalledWith(...);