Using @Spy and @Autowired together Using @Spy and @Autowired together spring spring

Using @Spy and @Autowired together


I know about these two options:

  1. Use @SpyBean annotation from spring-boot-test as the only annotation
@Autowired@InjectMocksprivate ProductController productController;@SpyBeanprivate ProductService productServiceSpy;
  1. Use Java reflection to "autowire" the spy object, e.g. ReflectionTestUtils
@Autowiredprivate ProductController productController;@Autowiredprivate ProductService productService;@Beforepublic void setUp() {    ProductService productServiceSpy = Mockito.spy(productService);    ReflectionTestUtils.setField(productController, "productService", productServiceSpy);}


I was surprised myself but it does work for us. We have plenty places like:

@Spy@Autowiredprivate FeatureService featureService;

I think I know why you are facing this problem. It's not about injection, it's about when(bloMock.doSomeStuff()).thenReturn(1) vs doReturn(1).when(bloMock).doSomeStuff().See: http://www.stevenschwenke.de/spyingWithMockito

The very important difference is that the first option will actually call the doSomeStuff()- method while the second will not. Both will cause doSomeStuff() to return the desired 1.


Using @Spy together with @Autowired works until you want to verify interaction between that spy and a different component that spy is injected into. What I found to work for me was the following approach found at https://dzone.com/articles/how-to-mock-spring-bean-version-2

@Configurationpublic class AddressServiceTestConfiguration {    @Bean    @Primary    public AddressService addressServiceSpy(AddressService addressService) {        return Mockito.spy(addressService);    }}

This turns your autowired component into a spy object, which will be used by your service and can be verified in your tests.