是的,这是 sinon@2 最常见的用例之一,但我相信您要寻找的既不是模拟也不是间谍,而是存根。
见:https://sinonjs.org/releases/v2.4.1/stubs/
var stub = sinon.stub(object, "foo");
//do your assertions
stub.restore(); //back to normal now.
这将允许您创建一个替换 object.foo() 的默认函数。
但是,从您的问题来看,听起来 no-op 存根函数不是您所追求的,而是想用您自己的自定义函数覆盖它:
var stub = sinon.stub(object, "foo", function customFoo() { /* ... */ });
//do your assertions
stub.restore(); //back to normal now.
HTH!
编辑:
如何存根单个函数:
以下存根object.sourceAttackTarget()
var stub = sinon.stub(object, "sourceAttackTarget", function sourceAttackTargetCustom(gameState, source, target) {
//do assertions on gameState, source, and target
// ...
return customReturn;
});
//do any further assertions
stub.restore(); //back to normal now.
如何存根函数以测试特定参数
var stub = sinon.stub(object, "sourceAttackTarget");
stub.withArgs(1, "foo", "bar").returns("correctTarget");
stub.returns("wrongTarget");
var output = object.sourceAttackTarget(gameState, source, target);
equal(output, "correctTarget", 'sourceAttackTarget invoked with the right arguments');
//do any further assertions
stub.restore(); //back to normal now.
(更新)
还有.calledWith() 和.calledWithMatch(),这是我刚刚发现的。也可以证明对这类测试非常有用。
如何只模拟一个对象的一种方法:
“Mocks 带有可能无法通过测试的内置期望。因此,它们强制执行实现细节。经验法则是:如果您不为某些特定调用添加断言,请不要模拟它。使用取而代之的是一个存根。一般来说,在一个测试中你永远不应该有超过一个模拟(可能有几个期望)。 - source
...所以对于上面提出的问题,模拟不是正确的选择,而存根是合适的选择。话虽如此,其中一个场景可以使用模拟轻松测试,即期望使用一组特定的参数调用方法。
var mock = sinon.mock(object);
mock.expects("sourceAttackTarget").withArgs(1, "foo", "bar");
object.sourceAttackTarget(gameState, source, target);
mock.verify();