#sinon
#sinon
Вопрос:
//user.dal
У меня есть эти два метода в user.dal, и я пытаюсь протестировать метод1, но внутри него есть запрос, вызываемый function1 (я хочу подделать результат этого) Я использую sinon.stub
export async function function1(id) {
try {
const result1 = await User.findOne({ _id: id });
return result1;
} catch (error) {
throw new Error('invalid user');
}
}
export async function method1(id, date) {
const request1 = await function1(id); // this is not faking its results
const request2 = await function2(request1); // this need to fake the results also
return request2;
}
//user.test
describe.only('get all information ', () => {
const id = '5c842bd3cf058d36711c6a9e';
const user = {
_id: '5c76f49e6df2131fe23a100a',
};
const date = '2019-03-09';
let spyFunction1;
beforeEach(async () => {
spyFunction1 = sinon.stub(userDal, 'function1').returns('this is my result');
});
afterEach(async () => {
await userModel.deleteOne({ _id: id });
spyFunction1.restore();
});
it('Should get.', async () => {
const result = await userDal.function1(id);
console.log('this is working well', result);
const badResult = await userDal.method1(id, date);
console.log('-->>>', badResult); // when its call to method 1, its calling to the method and not using the mock that I impemented before
});
});
Ответ №1:
Из import
документа:
Оператор static
import
используется для импорта привязок, которые экспортируются другим модулем.
Итак, когда вы делаете это:
import * as userDal from './user.dal';
результатом является то, что userDal
содержит привязки ко всему, что экспортируется user.dal
модулем.
Затем, когда вы делаете это:
sinon.stub(userDal, 'function1').returns('this is my result');
function1
привязка заменяется на stub
, которая возвращает 'this is my result'
.
Другими словами, модуль экспорта для function1
был заменен заглушкой.
Итак, когда выполняется эта строка:
const result = await userDal.function1(id);
он вызывает модуль export для function1
(который был заглушен), поэтому результат 'this is my result'
.
С другой стороны, когда выполняется эта строка:
const badResult = await userDal.method1(id, date);
он вводит method1
, который затем запускает эту строку:
const request1 = await function1(id); // this is not faking its results
для которого не вызывается модуль export function1
, он вызывается function1
напрямую.
Чтобы иметь возможность заглушки function1
и function2
внутри method1
, вы должны вызвать их модуль экспорта вместо того, чтобы вызывать их напрямую.
Для Node.js
модуля шаблон выглядит следующим образом:
const function1 = async function (id) { /* ... */ }
const function2 = async function (id) { /* ... */ }
const method1 = async function (id, date) {
const request1 = await exports.function1(id); // call the module export
const request2 = await exports.function2(request1); // call the module export
return request2;
}
exports.function1 = function1;
exports.function2 = function2;
exports.method1 = method1;
Для модуля ES6 шаблон аналогичен. Обратите внимание, что «Модули ES6 автоматически поддерживают циклические зависимости», поэтому мы можем import
вернуть модуль в себя, чтобы получить доступ к экспорту модуля:
import * as userDal from 'user.dal'; // import module into itself
export async function function1(id) { /* ... */ }
export async function function2(id) { /* ... */ }
export async function method1(id, date) {
const request1 = await userDal.function1(id); // call the module export
const request2 = await userDal.function2(request1); // call the module export
return request2;
}
Если вы последуете этому шаблону и вызовете модуль exports для function1
и function2
изнутри method1
, то когда вы замените модуль exports для этих двух функций заглушками, заглушки будут вызываться при вашем вызове method1
.
Комментарии:
1. Да, спасибо за совет, я перешел в другой файл и использую импорт и экспорт, и это работает хорошо. Большое вам спасибо
Ответ №2:
Я думаю, вам следует создать сигнатуру метода следующим образом: method1(id, date, function1, function2)
. По сути, вы бы передавали функцию 1 в качестве параметра. Тогда в вашем тесте вы можете вместо этого передать имитируемую функцию или заглушку, чтобы иметь возможность ее протестировать.
export async function function1(id) {
try {
const result1 = await User.findOne({ _id: id });
return result1;
} catch (error) {
throw new Error('invalid user');
}
}
export async function method1(id, date, function1, function2) {
const request1 = await function1(id);
const request2 = await function2(request1);
return request2;
}