All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mockito.Spy Maven / Gradle / Ivy

There is a newer version: 5.14.2
Show newest version
/*
 * 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 an 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!

*
    *
  1. 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);
     * 
    *
  2. * *
  3. 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.
  4. * *
  5. 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. *
  6. *
* *

* 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 {}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy