web-dev-qa-db-fra.com

Comment injecter une maquette dans un contexte printanier

J'ai un test qui utilise certains contextes Spring. Dans ces contextes, un certain nombre de haricots sont déclarés. Je veux que le test utilise l’implémentation réelle des beans des contextes, SAUF pour l’un d’eux, pour lequel je veux utiliser un MOCK.

J'ai essayé de transformer le composant Test en un composant de configuration (avec l'annotation @Configuration), mais le code XML semble avoir priorité sur l'annotation @Bean. Il ne fonctionne donc pas de la manière suivante:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"context1.xml", "context2.xml", ...})
@Configuration
public class MyTest{

    @Inject
    private MyTargetBean target;

    private AnotherBean myMock = mock(AnotherBean.class);

    @Bean
    public AnotherBean myMock() { return myMock; }

    .....

Je sais que je peux définir les Mocks en XML, mais pour cela, il me faudrait un fichier XML supplémentaire pour chaque test dans lequel je souhaite le faire. Je veux éviter cette complexité.

Existe-t-il un moyen d’injecter un haricot (comme une maquette) dans un contexte différent du XML?

Merci!

37
Mr.Eddart

C’est bien un duplicata de

l'injection de Mockito se moque d'un haricot de printemps

L'annotation Springockito est exactement ce que je cherchais

https://bitbucket.org/kubek2k/springockito/wiki/springockito-annotations

3
Mr.Eddart

Oui, vous êtes sur la bonne voie, mettre une maquette @Bean Dans une classe @Configuration Est une approche, et je vais décrire mon expérience:

L'astuce consiste à utiliser un jeu de fichiers .xml différent uniquement à des fins de test, ce qui exclut les versions en direct de ces beans.

@ContextConfiguration(locations = {"context1-test.xml", "context2-test.xml", ...})

Et les fichiers "-test-xml" vont dans src/test/resources.

Au moins c'était mon expérience de faire la même chose. Peut-être y a-t-il un moyen de "remplacer" les beans avec les versions simulées, mais je ne suis pas encore au courant.

J'ai aussi choisi de mettre les prototypes (j'avais 5 d'entre eux) tous ensemble dans une configuration propre:

@Configuration
public class MockServicesProvider {
     @Bean
     public AnotherBean myMock() { return mock(AnotherBean.class); }
}

Une autre partie intéressante de ce problème est l'utilisation courante de initMocks(this); dans la méthode @Before De votre classe de test.

Si les simulacres sont utilisés ailleurs (et ils le sont, c'est pourquoi vous les connectez ...), alors initMocks(this) les supprimera entre les tests (et non littéralement - ce ne sont que de nouveaux simulacres qui seront créés et toute autre maquette câblée dans d’autres objets sera "perdue").

La solution à cela était d'appeler la reset(mockObject) de mockito dans la méthode @Before Avant chaque test. Les mêmes simulacres sont réinitialisés (tous les when 'et leurs interactions), sans créer de nouveaux simulacres.

Notez que la documentation de Mockito pour reset dit très sévèrement que cette méthode ne devrait pas être couramment utilisée, sauf dans le contexte de simulations appliquées par injection de dépendance, comme nous le faisons effectivement dans ce cas :)

S'amuser!

35
vikingsteve