org.mockito.Spy Maven / Gradle / Ivy
Show all versions of mockito-core Show documentation
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockito;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import org.mockito.junit.MockitoJUnitRunner;
/**
* Allows shorthand wrapping of field instances in a spy object.
*
*
* Example:
*
*
* 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;
* private AutoCloseable closeable;
* @Before
* public void init() {
* closeable = MockitoAnnotations.openMocks(this);
* }
* @After
* public void release() throws Exception {
* closeable.close();
* }
* ...
* }
*
*
* Same as doing:
*
*
* Foo spyOnFoo = Mockito.spy(new Foo("argument"));
* Bar spyOnBar = Mockito.spy(new Bar());
*
*
*
* A 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!
*
* - Sometimes it's impossible or impractical to use {@link 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)
* when(spy.get(0)).thenReturn("foo");
*
* //You have to use doReturn() for stubbing
* doReturn("foo").when(spy).get(0);
*
*
*
* - 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 *un-stubbed* method is called *on the spy* but *not on the real instance*,
* you won't see any effects on the real instance.
*
* - 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.openMocks(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 openMocks() in your JUnit runner (@RunWith) or use the built-in
* {@link MockitoJUnitRunner}. Also, make sure to release any mocks after disposing your test class with a
* corresponding hook.
*
*
* Note that the spy won't have any annotations of the spied type, because CGLIB won't rewrite them.
* It may troublesome for code that rely on the spy to have these annotations.
*
* @see Mockito#spy(Object)
* @see Mock
* @see InjectMocks
* @see MockitoAnnotations#openMocks(Object)
* @see MockitoJUnitRunner
* @since 1.8.3
*/
@Retention(RUNTIME)
@Target(FIELD)
@Documented
public @interface Spy {}