cleishm / jsmockito

Javascript mocking framework inspired by the awesome mockito
http://jsmockito.org
Other
106 stars 19 forks source link

Stubbing same method always returns first value #6

Closed HitmanInWis closed 13 years ago

HitmanInWis commented 13 years ago

If I stub the same mock function twice, I only ever receive the value from the initial stub.

    var func = mockFunction();
    when(func)().thenReturn("a");
    alert(func());
    when(func)().thenReturn("b");
    alert(func());

Both alerts show "a", whereas I expected the first to show "a" and the second to show "b". I know the argument could be made that this should be two separate unit tests (i.e. two separate mock functions), but sometimes it's nice to be able to check a few similar conditions in the same function.

cleishm commented 13 years ago

This is as expected. In the same manner as mockito, "Last stubbing is more important - when you stubbed the same method with the same (or overlapping) matchers many times".

This is actually very useful, as it allows you to stub with overlapping matchers to return certain values for specific arguments, and fall back to a more general return value for everything else.

To achieve what you want, you can pass an array to the stubbing methods with multiple values to return in order, or chain the calls.

cleishm commented 13 years ago

Oh, there was an issue with last stubbing (#3), which is fixed in HEAD. I suggest using that (I will do a new release soon).

HitmanInWis commented 13 years ago

Thanks Chris. The patch from #3 did indeed fix this issue.

cleishm commented 13 years ago

To be clear, it's usually better to setup all your stubs before invoking the methods, rather than interleaving as in your example. But I'm glad this now works as you'd like!

HitmanInWis commented 13 years ago

I tried chaining the return as such:

when(func)().thenReturn("a").thenReturn("b");

but I get an error indicating that the return value from thenReturn("a") is undefined.

I also tried

when(func)().thenReturn(["a", "b"]);

but then my return value was an array of both values instead of the first value on the first call, and the second value on the second call.

Is there documentation on how I should be doing this correctly?

cleishm commented 13 years ago

I'm sorry, I wasn't clear - I should have said to pass multiple arguments to thenReturn (or then, or thenThrow), not an actual array. E.g. exactly what you have without the square brackets.

Also, I noticed a small issue with the chaining off thenReturn, which is now fixed in HEAD.

HitmanInWis commented 13 years ago

Excellent, thanks for the explanations!