2
votes

Comment remplacer un bean par une maquette de test dans Spring Boot pour les tests d'intégration

J'ai une application de printemps et des tests d'intégration pour cette application. Je voudrais remplacer un haricot par un haricot simulé.

Mon vrai bean ressemble à ceci

@Autowired
private IMyService myService;

et pour le test je voudrais qu'il soit remplacé

@Service
@Profile("!test")
public class MyService implements IMyService {

}

@Service
@Profile("test")
public class TestMyService implements IMyService {

}

Tous Je peux penser à utiliser des profils pour différents services. Par exemple:

@Service
public class TestMyService {

}

Et puis je filme automatiquement le bean comme ceci

@Service
public class MyService {

}

Y a-t-il un meilleur moyen? P >


0 commentaires

3 Réponses :


1
votes

Ma préférence personnelle est d'éviter de charger le contexte de compétition pour les tests. Par conséquent, j'aime que mon test se concentre sur un sous-ensemble de beans. Cela signifie généralement que je décris les beans que j'utilise dans les tests:

@RunWith(SpringRunner.class)
@SpringBootTest(
        classes = MyTest.Cfg.class
)
public class MyTest {

    @Import({
        // .. some classes to import
    })
    @Configuration
    public static class Cfg {

        @Bean
        public IMyService service() {
            IMyService mock = Mockito.mock(IMyService.class);
            when(mock.someMethod()).thenReturn("some data");

            return mock;
        }

    }

}

Si plus de configuration est nécessaire, j'ai tendance à préparer une classe de configuration distincte pour les tests:

@RunWith(SpringRunner.class)
@SpringBootTest(
        classes = MyTest.Cfg.class
)
public class MyTest {

    @Import({
        // .. some classes to import including TestMyService.class
    })
    @Configuration
    public static class Cfg {

    }

}


3 commentaires

cool. Vous vous retrouvez alors avec 10, 20 ou 30 beans dans la section @Import ?


J'ai plusieurs configurations avec une application (type de modules / packages) où je configure principalement des dépendances externes (adaptateurs, ports suivants et architecture d'adaptateurs). Ce qui m'aide avec l'encapsulation. En parcourant le code, je ne vois pas plus de 6 à 8 importations dans un seul test.


Agréable! J'avais du mal à utiliser @Spybean, ce qui ne fonctionnait pas, peu importe comment je l'utilisais ... merci!



0
votes

Vous pouvez nommer vos beans, dans votre cas quelque chose comme

@Qualifier("testService")
@Autowired
private IMyService myService;

et dans votre classe de test, vous pouvez demander explicitement un service de test en utilisant @Qualifier , comme

@Service("testService")    
public class TestMyService implements IMyService {

}


1 commentaires

Cette approche ne fonctionne pas lorsque IMyService est une dépendance en aval (un adaptateur) dans votre code métier. @Qualifier vous permet d'injecter le bean dans la classe de test, mais c'est très limitant.



1
votes

Spring Boot a des annotations @MockBean et @SpyBean exactement à cet effet:

https: //docs.spring. io / spring-boot / docs / current / reference / html / boot-features-testing.html # boot-features-testing-spring-boot-applications-mocking-beans

La déclaration est simple:

@MockBean
private MyService myService;

Spring Boot y injectera Mockito mock au lieu du bean réel.


0 commentaires