Мне нужна функция calls(f)
на заглушках, которая позволяет мне выполнять произвольный код при вызове заглушки. Эта функция f
могла получить все аргументы, с которыми была вызвана исходная функция.
Я с радостью предоставлю для этого пул-реквест, но сначала я хотел бы убедиться, что он будет принят.
Это уже существует:
sinon.stub(obj, "meth", function () {
// Whatever you want in here
});
Блестяще! И это тоже есть в документации! Извините, как-то пропустил.
Я голосую за повторное открытие по следующим причинам:
// Argument matching
var stub = sinon.stub();
stub.withArgs("a").calls(f);
stub.withArgs("b").returns(something);
Уже есть способ выполнить настраиваемую логику. Я вообще считаю, что нетривиальная логика в тестах - плохая идея, и не хочу поощрять ее дальнейшими функциями в этом направлении.
Я бы не сказал, что издевательство над контрактом в тесте - плохая идея или что это должно быть нетривиально. Примером может служить обработчик запросов в маршрутизаторе:
var mockRequest = sinon.stub();
mockRequest.withArgs(someReq, someRes).calls(function(req, res) {
res.send('mock result 1');
});
mockRequest.withArgs(someOtherReq, someOtherRes).calls(function(req, res) {
res.send('mock result 2');
});
Конечно, этого можно добиться с помощью «yieldsTo», но я думаю, что это неочевидно и не очень хорошо читается.
Однако я понимаю, что вы не хотите добавлять уже большой api.
Я тоже придерживался этого:
var mockRequest = sinon.stub();
mockRequest.onThirdCall().calls(function() {
console.log('Yes!');
done();
});
Требуются любые подсказки о том, как этого можно достичь. :(
Это было бы очень полезно. А пока мне нужно сделать для этого свою собственную функцию-заглушку :(
Почему должны быть объект и «метод», чтобы можно было заглушить (fn)? Я не могу понять, в чем разница со шпионом (фн)?
+1 к комментарию @shakiba . «Ответ» здесь, sinon.stub(obj, "meth", function () { ... })
, работает только при установке метода на объект. При создании автономной заглушки метода с sinon.stub()
(например, чтобы передать что-то еще в качестве прослушивателя событий или обратного вызова), вы не можете использовать это решение.
Обходной путь уродливый:
var fakeObject = { fn: function () { } };
sinon.stub(fakeObject, "fn", function () { ... });
var stubIWanted = fakeObject.fn;
Я бы предпочел чистый синтаксис вроде:
var stubIWanted = sinon.stub(function () { ... });
@peterflynn Вы можете сделать это со шпионом:
var spyYouWant = sinon.spy(function () { ... });
@mantoni шпион не позволяет вам определять различное поведение для разных вызовов.
У меня также есть вариант использования для stub.onSecondCall().calls(function() {})
. Я хочу выполнять свои собственные утверждения во время этих звонков.
+1 за вариант использования
+1 за изменение , предложенное
@ChiperSoft Вы вполне способны самостоятельно определять разное поведение для разных вызовов. Просто проверьте кол-во звонков в шпионе.
@bion Мы пытаемся уменьшить API до версии 2.0. Посмотрите, можете ли вы создать оболочку / плагин для расширения основных функций, если вы считаете, что это полезно, и опубликуйте их в NPM, если они вам подходят.
В итоге я создал свою собственную библиотеку заглушек функций, которая позволяла мне определять обратные вызовы для каждого вызова. Это значительно упрощает тесты и позволяет мне полностью удалить sinon из моих проектов. http://npm.im/stepperbox
моя заглушка выполняет исходный метод, почему
@ppyoosuf, пожалуйста, отправляйте вопросы об использовании в список рассылки или переполнение стека после просмотра документации. Если вы обнаружите актуальную проблему / ошибку, попробуйте открыть новую проблему и разместите достаточно кода, чтобы мы могли проверить проблему.
это моя функция контроллера в node.js
export.searchDocument = функция (req, res) {var type = req.query.docType; вар
dep = req.query.dep; var serStr = req.query.serStr; var результат; //
console.log (req.session.userMode); res.writeHead (200, {"Content-Type":
"application / json"});
if(type===''||type===null || isNaN(type) ||dep===''||dep===null)
// console.log("type:"+type+"dep="+dep);
if(type==='-1' && dep==='-1')
{
docService.getAllDoc(serStr,function(err,data){
if(err) throw err;
result=data;
res.end(JSON.stringify(result));
});
}
else if(type==='-1')
docService.getDocByDep(serStr,dep,function(err,data){
if(err) throw err;
result=data;
res.end(JSON.stringify(result));
});
else if(dep==='-1')
docService.getDocByType(serStr,type,function(err,data){
if(err) throw err;
result=data;
res.end(JSON.stringify(result));
});
else
**docService.getDocByTypeDep**(serStr,type,dep,function(err,data){
console.log(data);
console.log(err);
if(err) throw err;
result=data;
res.end(JSON.stringify(result));
});
};
здесь docService.getDocByTypeDep - это функция службы базы данных
this.getDocByTypeDep = function (ser, typeId, depId, cb) {
var myErr = null, data = null;
if (typeId == null || typeId == '' || depId == null || depId == '') return
cb ("ошибка", данные);
var qry = "";
con.query (qry, typeId, function (err, res) {
если (ошибка)
{
myErr = err;
cb (myErr, данные);
}
еще
{
data = res;
cb (myErr, данные);
}
});
};
Я написал тестовые примеры с помощью sinon stub, но он выполнял исходную функцию
it('returns the result', function(done) {
var stub = sinon.stub(docService, 'getDocByTypeDep');
var req = {
query:{
docType: '2',
dep:'4',
serStr:"a"
}
};
// we provide the response object which the controller uses
var res = {
end: function(data) {
expect(data).to.be.a("string");
stub.restore();
done();
},
writeHead:function(){
}
};
// var error = new Error('Authentication failed.');
stub.callsArgWithAsync(3,error,error);
controllerToTest.searchDocument(req,res); // call the function
для проверки
});
please help me
В чт, 23 июня 2016 г., в 12:16, Карл-Эрик Копсенг <
[email protected]> написал:
@ppyoosuf https://github.com/ppyoosuf, пожалуйста, задавайте вопросы об использовании по адресу
список рассылки или переполнение стека после просмотра документации. Если вы найдете
актуальная проблема / ошибка, попробуйте открыть новую проблему и отправьте нам достаточно кода, чтобы
проверьте проблему.-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/sinonjs/sinon/issues/118#issuecomment -227964049 или отключить звук
нить
https://github.com/notifications/unsubscribe/APpoQazXq7BUm113wp7--RlxDaukOcMYks5qOivEgaJpZM4BSxXv
.
@ppyoosuf Мы стараемся, чтобы список проблем GitHub был аккуратным и сосредоточился на ошибках и обсуждениях функций. Это вопрос использования, отправьте его в список рассылки Sinon.JS , чтобы более
Ok
Без этой функции использование фальшивых таймеров затруднительно.
У меня есть метод, который вызывается внутри черного ящика несколько раз с таймаутом, чтобы проверить черный ящик, мне нужно иметь возможность управлять часами.
Поэтому я хочу вызывать clock.tick
каждый раз при попадании в определенную заглушку, также я определил поведение для этой заглушки через withArgs
и yields
.
Хотелось бы увидеть что-то вроде:
var clock = sinong.useFakeTimers();
var stubbedMethod = sinon.stub();
stubbedMethod.onHit(()=>clock.tick(1000)).withArgs('page1').yields(null, [12, 45, 69]);
Это возможно только за счет специальной конструкции заглушки, что не всегда удобно или возможно:
sinon.stub(object, 'method', function(callback){
clock.tick(1000);
callback();
})
Возможность изменять состояние теста / среды по вызову важна для множества различных тестов и крайне важна для наличия в макетной библиотеке.
в sinon 2.1 callsFake()
будет делать именно это
Я не видел этого решения, размещенного выше, поэтому добавляю, если оно помогает другим:
Использование шпионского интерфейса для получения аргументов n-го вызова
var someFunctionSpy = sinon.spy(someFunction)
someFunction()
var nthCallArgs = someFunctionSpy.getCall(n)
Самый полезный комментарий
@mantoni шпион не позволяет вам определять различное поведение для разных вызовов.
У меня также есть вариант использования для
stub.onSecondCall().calls(function() {})
. Я хочу выполнять свои собственные утверждения во время этих звонков.