mockito - What is the point of a spied instance -
i debugging test using spy
, found confusing.
public class spytest { @test public void testspy1(){ thing thing = new thing(); thing thingspy = mockito.spy(thing); thingspy.modify("bar"); assertthat(thing.getfoo(), is("bar")); } @test public void testspy2(){ thing thing = new thing(); thing thingspy = mockito.spy(thing); thingspy.modify("bar"); assertthat(thingspy.getfoo(), is("bar")); } private static class thing { private string foo = ""; public void modify(string foo){ this.foo = foo; } public string getfoo() { return foo; } } }
i expected spy defer passed instance.
testspy1
fails , testspy2
succeeds, because tried read data actual object instead of spy. so, if spy not interact passed object, why accept 1 , why keep around in mock settings?
a spy makes shallow copy of fields of passed object. mocks don't use normal constructors or initializers, in normal mockito mock, of fields stay in default state (0, null, false, etc). can make hard call real methods on mock, since many instance methods interact of instance's state, , uninitialized fields invalid. allowing normal construction, , copying state, spy object can behave normal object—except stubbing , verification capabilities mockito provides.
though use normal mockito-created mock , set fields, tend break encapsulation, , in case not make easy set private or final fields. current spy syntax, can call constructor of choice parameters of choice , set class accurately possible.
but why not keep old object , delegate it? answer this
:
class anotherthing { string greet() { return "hello " + getname() + "!"; } string getname() { return "world"; } } class anotherthingtest { void testoverridename() { anotherthing anotherthing = new anotherthing(); anotherthing spyofanotherthing = spy(anotherthing); doreturn("dolly").when(spyofanotherthing).getname(); assertequals("hello dolly!", spyofanotherthing.greet()); // fails! } }
the above seems reasonable test, if mockito delegate anotherthing instance, fail: spyofanotherthing
delegate anotherthing
, call getname
(explicitly this.getname()
) on itself, return default "world". in order partial mocking work, value of this
must identical between spy implementation , original implementation, , requires copy.
for reason, you'll see spy(new classtospy())
, developer not keep reference spy's original object. can avoid confusion instance interact with, , highly recommend it.
Comments
Post a Comment