Reputation: 511
From the documentation:
A spy is always based on a real object. Hence you must provide a class type rather than an interface type, along with any constructor arguments for the type. If no constructor arguments are provided, the type’s default constructor will be used.
Method calls on a spy are automatically delegated to the real object. Likewise, values returned from the real object’s methods are passed back to the caller via the spy.
Also:
When stubbing a method on a spy, the real method no longer gets called:
subscriber.receive(_) >> "ok"
Instead of calling SubscriberImpl.receive, the receive method will now simply return "ok".
If a spy is just an interface layer between a real object and the caller, why not just use the real object? What does using a spy offer that using the real object or a Mock do not?
It seems to be in this void between a Mock and a real object to me.
Upvotes: 2
Views: 1230
Reputation: 13242
Spies can be used in different scenarios. However, it is good if you can implement your tests without resorting to spies.
(Think twice before using this feature. It might be better to change the design of the code under specification.)
// this is now the object under specification, not a collaborator
def persister = Spy(MessagePersister) {
// stub a call on the same object
isPersistable(_) >> true
}
when:
persister.receive("msg")
then:
// demand a call on the same object
1 * persister.persist("msg")
Example and quote are from the docs @ http://spockframework.org/spock/docs/1.1/all_in_one.html#Spies
Upvotes: 3
Reputation: 2297
In my practice I prefer to use a real objects as much as possible. In case when only one method is to be mocked I still use a real object but with overridden needed method:
MyDomainClass myRealObjectWithMockedMethod = new MyDomainClass() {
@Override
Object doSomething() {
return "hard coded or mocked result";
}
}
// test what you need
myRealObjectWithMockedMethod.action();
Note, this way works only of overridden method is not final. Otherwise Spy will help to define a behavior of this method.
Upvotes: 1
Reputation: 11470
A spy offers the possibility to use the original object but also mock out one method. For example you have a class where you want to test the implementation of the toString()
method. But this calls an long running method which needs some external access like a database. In this case you use a spy and let your long running method return some test string and then use the toString
from the original object.
Or like the spock example the method subscriber.receive
maybe needs a server which sends out asynchronous messages. To write an test for subscriber
not relying on the server or to handle asynchronous complexity you let the spy return ok
and can easily test your methods which will rely on a server ok
.
Upvotes: 0