Annotation Type Spy

public @interface Spy

Allows shorthand wrapping of field instances in an spy object.


 public class Test{
    //Instance for spying is created by calling constructor explicitly:
    @Spy Foo spyOnFoo = new Foo("argument");
    //Instance for spying is created by mockito via reflection (only default constructors supported): 
    @Spy Bar spyOnBar;
    public void init(){

Same as doing:

 Foo spyOnFoo = Mockito.spy(new Foo("argument"));
 Bar spyOnFoo = Mockito.spy(new Bar());

The field annotated with @Spy can be initialized by Mockito if a zero argument constructor can be found in the type (even private). But Mockito cannot instantiate inner classes, local classes, abstract classes and interfaces. The field annotated with @Spy can be initialized explicitly at declaration point. Alternatively, if you don't provide the instance Mockito will try to find zero argument constructor (even private) and create an instance for you. But Mockito cannot instantiate inner classes, local classes, abstract classes and interfaces. For example this class can be instantiated by Mockito :

public class Bar {
    private Bar() {}
    public Bar(String publicConstructorWithOneArg) {}

Important gotcha on spying real objects!

  1. Sometimes it's impossible or impractical to use Mockito.when(Object) for stubbing spies. Therefore for spies it is recommended to always use doReturn|Answer|Throw()|CallRealMethod family of methods for stubbing. Example:
       List list = new LinkedList();
       List spy = spy(list);
       //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
       //You have to use doReturn() for stubbing
  2. Mockito *does not* delegate calls to the passed real instance, instead it actually creates a copy of it. So if you keep the real instance and interact with it, don't expect the spied to be aware of those interaction and their effect on real instance state. The corollary is that when an *unstubbed* method is called *on the spy* but *not on the real instance*, you won't see any effects on the real instance.
  3. Watch out for final methods. Mockito doesn't mock final methods so the bottom line is: when you spy on real objects + you try to stub a final method = trouble. Also you won't be able to verify those method as well.

One last warning : if you call MockitoAnnotations.initMocks(this) in a super class constructor then this will not work. It is because fields in subclass are only instantiated after super class constructor has returned. It's better to use @Before. Instead you can also put initMocks() in your JUnit runner (@RunWith) or use the built-in MockitoJUnitRunner.

See Also:
Mockito.spy(Object), Mock, InjectMocks, MockitoAnnotations.initMocks(Object), MockitoJUnitRunner