web-dev-qa-db-fra.com

Utiliser @Spy et @Autowired ensemble

J'ai une classe de service avec 3 méthodes, la classe de service utilise également des annotations @Autowired. Sur 3 méthodes, je veux me moquer de deux méthodes mais utiliser la vraie méthode pour la 3ème.

Le problème est:

  1. Si j'utilise @Autowired avec @Spy, les trois implémentations de méthodes réelles sont appelées.
  2. Si j'utilise uniquement @Spy, l'appel à la méthode réelle est de retour avec le pointeur Null car il n'y a pas d'initialisation des objets Autowired.
11
Shashi K Kalia

Je connais ces deux options:

  1. Utilisez @ SpyBean annotation de spring-boot-test comme seule annotation
@Autowired
@InjectMocks
private ProductController productController;

@SpyBean
private ProductService productServiceSpy;
  1. Utilisez Java réflexion pour "câbler automatiquement" l'objet espion, par exemple ReflectionTestUtils
@Autowired
private ProductController productController;

@Autowired
private ProductService productService;

@Before
public void setUp() {
    ProductService productServiceSpy = Mockito.spy(productService);
    ReflectionTestUtils.setField(productController, "productService", productServiceSpy);
}
20
PROrock

J'ai été moi-même surpris, mais cela fonctionne pour nous. Nous avons beaucoup d'endroits comme:

@Spy
@Autowired
private FeatureService featureService;

Je pense que je sais pourquoi vous êtes confronté à ce problème. Il ne s'agit pas d'injection, il s'agit de when(bloMock.doSomeStuff()).thenReturn(1) vs doReturn(1).when(bloMock).doSomeStuff(). Voir: http://www.stevenschwenke.de/spyingWithMockito

La différence très importante est que la première option appellera en fait la méthode doSomeStuff () - tandis que la seconde ne le fera pas. Les deux entraîneront doSomeStuff () pour retourner le 1 souhaité.

6
yuranos87

En utilisant @Spy ensemble avec @Autowired fonctionne jusqu'à ce que vous souhaitiez vérifier l'interaction entre cet espion et un composant différent dans lequel cet espion est injecté. Ce que j'ai trouvé pour travailler était l'approche suivante trouvée sur https://dzone.com/articles/how-to-mock-spring-bean-version-2

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

Cela transforme votre composant câblé automatiquement en un objet espion, qui sera utilisé par votre service et pourra être vérifié dans vos tests.

0
Jakub Zawadzki