Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Spy.andCallThrough should be default behaviour #88

maenu opened this Issue · 19 comments

I don't see the point in having to explicitly state that a spy should call the wrapped method. I stepped into this trap by assuming it was the default behaviour - which it is not. In my opinion, having a spy on a method should not change the program flow by default, but just cache arguments etc. as it already does.


+1 for this. If i dont want it to be called ill want it it to be explicit. A andDontCall method can be added for the cases when you dont want the spied function to be called. The oposite, like it is today, does not looks natural.

Of course it will break BC and a 2.0 version should be release after this change, IMHO.


Marking as 2.0.

Interesting. Can you start this discussion on the Jasmine email list? I'd be curious on a broader vote on this topic.


I think this change would certainly be more compatible with what somebody would naturally assume based on the name "spy".


To play devil's advocate, none of the major Ruby mocking frameworks (rspec, rr, mocha) do this by default. It would be surprising coming from a Ruby world, I think. I'm not sure about any other languages, but my guess is that Java et al. don't do this either.



A spy is a test double (as in, stand-in), like any other (stub, mock, fake). The name does not (intend to) convey that they're any more real than any other test double. [aside: I think rr and mockito in particular have muddied this issue, by using names like spies and proxies for what are essentially partial mocks.]

I believe strongly that the current behavior is the correct one. Since I use Jasmine exclusively for isolated unit testing, I explicitly spy to isolate the subject code from depended-on-components.

Unless I'm writing a functional characterization test around some legacy code, I don't want the subject to call through the real depended-on function, and for a number of reasons--not the least of which is that I don't want to perform whatever amount of setup is needed to sate the internal behavior of each depended-on function in order to exercise the subject code, as it makes the spec less readable and provides no value. In a BDD rhythm, most unit tests should be driven by a full-stack test (a la Cucumber) anyway, so the value of calling through to the real method is suspect.

As for Ruby's test double frameworks, I've written in the past why they aren't fantastic at facilitating isolated unit testing and when I speak on Jasmine, its superior test double facility is something I frequently point out as an advantage over popular Ruby test double libraries.

@mcmire - in Java, the most popular test double library is Mockito, and it argues strongly against calling through to the actual component. Mockito mocks behaves more or less like Jasmine spies (and the author has acknowledged the naming mismatch of Mockito spies, which are essentially partial mocks.)



I'm with @searls on this one. Most other mocking frameworks do not call through by default so personally I wouldn't expect this behavior.

It is a bummer that this isn't clear via the name "spy" but I would rather see a breaking change (or deprecation) around renaming spy than changing the default behavior to call through.



This goes against the principle of testing units in isolation, and as such the user should suffer the syntactic vinegar.



I'm with @searls on this, if its behavior at all it should at least be explicit



I agree with @searls' argument, let's keep it as an explicit feature.



I agree with the reasoning offered by @searls and @magnusstahre. I think of a spy as a flight recorder. I'll use a spy to help describe and verify the interactions between the subject of the spec & its collaborators. To do that, I just need the flight recorder to remember that the collaborator was called. The existing behavior of Jasmine spies helps encourage spec'ing the subject of the spec in isolation.



@searls and @magnusstahre have it right.

Spying should only be important for isolation tests. For integration tests, the important thing should not be what is passed to the external routine, but what the result of calling the external routine is.

Asserting on call parameters in an integration test is a dangerous practice, because it can make you think you've proved something you haven't.

In an isolation test, calling through is counterproductive. Do you know why professional pilots with thousands of hours of experience still train in simulators rather than real airplanes? Because the simulators allow them to confront conditions that would be prohibitively dangerous, expensive, or difficult to produce in a real airplane. Same with isolation tests. You want reality only in the layer between the tests and the mocks, and you want to squeeze that layer as thin as you can get it. Everywhere else, you want enough complete control to be able to easily introduce unlikely, hard-to-reproduce that in production, when those unlikely conditions actually occur, your code will still be operating in tested problem space and its behavior will be as expected.

I think the ability to call through at all is suspect; making it the default would produce a flood of badly-conceived, low-value, maintenance-heavy tests from Agile beginners who haven't found their sea legs yet. Make it easy to do the right thing and harder to do the wrong thing, not the other way around.



Seems like booty



If only for the fact that the number of times I would have to modify my tests to explicitly avoid .andCallThrough would increase exponentially. The current behaviour is doing it right, as has been mentioned by many other commenters.

As a potential compromise I'd be willing to listen to suggestions for name changes to the spy function so that the intent of a "spy" is perhaps revealed better.


+/- 0

+1 in that the word spy somewhat (see -1 below) implies something different than what it does (the 'ol p6spy jdbc driver still makes call to the database)

-1 good testing in isolation requires test doubles which is what spies are doing for jasmine today and breaking that would be bad. The terminology mixup of test-doubles (dummy/spy/stub/mock/fake) in the world of testing frameworks is such a mess that it doesn't really matter what you call it.


Seems like I do not have the same understanding of what a Spy is as the majority. My initial perception was that a Spy was - in the first place - some sort of a middle-man that can be used to silently intercept the flow of a program without actually affecting it, and the ability to mock behaviour was rather a useful side-effect. I derived this from the name Spy: A spy tells a third party what is going on without letting the others know. A spy that is just a stub, that doesn't do anything until he's told to really do it, would be busted quite fast (or is James Bond).
I would then suggest to rename the Spy to something that implicates the mocking intention a bit better (Fake, Dummy).


From what I've seen in the Ruby world, it works like this:

Stub can does-a Proxy
Mock does-a Stub
Spy is-a-kind-of Mock

A stub lets you replace a method with another implementation. You can also have a proxy, where you don't completely replace the method with the implementation, but you intercept the method's return value and you can do whatever you want with that before it gets returned from the method. I suppose you could also call stubs called fakes or dummies.

A mock stubs a method but then lets you assert that the method was called (optionally with arguments).

A spy is just another "flavor" of mock -- that is, you still stub a method and you still can assert the method was called. The only thing that differs between mocks and spies is that with a mock you assert the stubbed method was called before you've called the method you are testing. With a spy, you make the assertion AFTER.

A "test double" wraps up all of these concepts (stub, mock, spies, etc.).

That is what I understand the difference to be (mostly taken from Ruby's rr library)... whether or not any of this is actually true, I'm not sure. But I think Jasmine uses these definitions too.


-1 for me


+/- 0

-1 The wiki page on Spies ( clearly states the functionality:

Jasmine integrates 'spies' that permit many spying, mocking, and faking behaviors.
A 'spy' replaces the function it is spying on.

+1 Agree with @krsmes about questionable naming of the Klass.


As part of the clean-up around 2.0, I'm closing this. No change planned.

@infews infews closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.