web-dev-qa-db-fra.com

Remplacement d'un bean autowired dans les tests unitaires

Existe-t-il un moyen simple de remplacer un bean autowired dans des tests unitaires spécifiques? Il n'y a qu'un seul bean de chaque type dans les classes de compilation, de sorte que le câblage automatique ne pose pas de problème dans ce cas. Les classes de test contiendraient des simulacres supplémentaires. Lors de l'exécution d'un test unitaire, j'aimerais simplement spécifier une configuration supplémentaire qui dit en gros, lors de l'exécution de ce test d'utilisation, utilisez ce modèle au lieu du bean standard.

Les profils semblent un peu excessifs pour ce dont j'ai besoin et je ne suis pas sûr que cela serait réalisable avec l'annotation Primaire, car différents tests unitaires pourraient avoir différentes simulacres.

42
samblake

Si vous voulez simplement fournir un haricot différent dans vos tests, je pense que vous n'avez pas besoin d'utiliser des profils de ressort ou de mockito.

Il suffit de faire ce qui suit:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { TestConfig.class })
public class MyTest
{
    @Configuration
    @Import(Application.class) // the actual configuration
    public static class TestConfig
    {
        @Bean
        public IMyService myService()
        {
            return new MockedMyService();
        }
    }

    @Test
    public void test()
    {
        ....
    }
}

NOTE: testé avec soufflet à ressort 1.3.2/ressort 4.2.4

62
teo

Dans Spring Boot 1.4, il existe un moyen simple de le faire:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { MyApplication.class })
public class MyTests {
    @MockBean
    private MyBeanClass myTestBean;

    @Before
    public void setup() {
         ...
         when(myTestBean.doSomething()).thenReturn(someResult);
    }

    @Test
    public void test() {
         // MyBeanClass bean is replaced with myTestBean in the ApplicationContext here
    }
}
39
Sergey Shcherbakov

J'ai eu un problème similaire et j'ai résolu avec un mélange et je trouve celui-ci plus utile et réutilisable. J'ai créé un profil Spring pour les tests et une classe de configuration qui remplace les beans que je veux simuler de manière très simple: 

@Profile("test")
@Configuration
@Import(ApplicationConfiguration.class)
public class ConfigurationTests {

    @MockBean
    private Producer kafkaProducer;

    @MockBean
    private SlackNotifier slackNotifier;

}

En faisant cela, je peux @Autowire ces simulacres de haricots et utiliser mockito pour les vérifier. Le principal avantage est que tous les tests obtiennent maintenant de manière transparente les beans factices sans aucune modification par test. Testé avec:

botte à ressort 1.4.2

4
Israel Fernández

Vous devez utiliser les profils de printemps afin de savoir quel type de haricot vous souhaitez utiliser dans différents contextes.

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

1
Eddú Meléndez

Comme l'a commenté mats.nowak, @ContextConfiguration est utile pour cela.

Dire une classe de test parent est comme:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/some-dao-stuff.xml"
    ,"classpath:spring/some-rest-stuff.xml"
    ,"classpath:spring/some-common-stuff.xml"
    ,"classpath:spring/some-aop-stuff.xml"
    ,"classpath:spring/some-logging-stuff.xml"
    ,"classpath:spring/some-services-etc.xml"
})
public class MyCompaniesBigTestSpringConfig {
...

Créez une classe de test enfant:

package x.y.z;
@ContextConfiguration
public class MyOneOffTest extends MyCompaniesBigTestSpringConfig {
...

et mettez dans src/test/resources/x/y/z/MyOneOffTest-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd">


    <bean id="widgetsService" class="com.mycompany.mydept.myservice.WidgetsService" primary="true" />

</beans>

Ce bean widgetsService remplacera le bean défini dans le fichier de configuration principal xml (ou dans la configuration Java). Voir à propos de inheritLocations Notez également le fichier par défaut -context.xml. Exemple de cela ici . Mise à jour: Je devais ajouter primary="true", apparemment c'est nécessaire.

0
user1527469