Monday, May 20, 2024
63
rated 0 times [  67] [ 4]  / answers: 1 / hits: 13882  / 10 Years ago, thu, july 24, 2014, 12:00:00

I've got a single method in my namespace that I'd like to mock, but I'd prefer that all the others work normally. Is it possible to have sinon mock a specific method while leaving the others the same?



My understanding is I'm not looking for a spy because I want to assert that the mock was called with specific parameters.



Here's my code in CoffeeScript:



root.targeting.handleUnitsAttack = (gameState) ->
units = gameState.heroes.concat(gameState.badGuys)
for source in units
for target in units
gameState = root.targeting.sourceAttackTarget(gameState, source, target)
gameState


I'd like to mock sourceAttackTarget and verify that its arguments are specific values.


More From » coffeescript

 Answers
2

Yes, that is one of the most common uses cases for sinon@2, but I believe that what you are looking for is neither a mock nor a spy, but instead a stub.


See: https://sinonjs.org/releases/v2.4.1/stubs/


var stub = sinon.stub(object, "foo");
//do your assertions
stub.restore(); //back to normal now.

This will allow you to create a default function that replaces object.foo().


From your question, however, it sounds like a no-op stub function is not what you are after, and instead want to override it with a custom function of your own:


var stub = sinon.stub(object, "foo", function customFoo() { /* ... */ });
//do your assertions
stub.restore(); //back to normal now.

HTH!




EDIT:


How to stub a single function:


The following stubs 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.

How to stub a function to test for particular parameters


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.

(Update)


There is also .calledWith() and .calledWithMatch(), which I just found out about. Could also prove quite useful for these sorts of tests.


How to mock just one method for an object:


"Mocks come with built-in expectations that may fail your test. Thus, they enforce implementation details. The rule of thumb is: if you wouldn’t add an assertion for some specific call, don’t mock it. Use a stub instead. In general you should never have more than one mock (possibly with several expectations) in a single test." - source


... so for the question asked above, a mock is not the right thing to use, and a stub is the appropriate choice. That being said, one of the scenarios can be tested easily with a mock, and that is the expectation that a method has been called with a particular set of arguments.


var mock = sinon.mock(object);
mock.expects("sourceAttackTarget").withArgs(1, "foo", "bar");
object.sourceAttackTarget(gameState, source, target);
mock.verify();

[#43644] Wednesday, July 23, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
agustindejonm

Total Points: 738
Total Questions: 84
Total Answers: 84

Location: Northern Ireland
Member since Mon, Nov 14, 2022
2 Years ago
agustindejonm questions
Fri, Jun 25, 21, 00:00, 3 Years ago
Fri, Sep 18, 20, 00:00, 4 Years ago
Sat, May 16, 20, 00:00, 4 Years ago
;