J'essaie de remplacer un bean Spring lors d'un test déclaré dans une configuration de test avec l'utilisation de @Primary. Une déclaration se trouve dans le chemin src/main/Java, l'autre, la principale, dans le chemin src/test/Java.
Cependant, Spring remplace intentionnellement le bean principal par le bean non primaire, celui que je ne veux pas utiliser pour le test. Si je commente simplement le bean de configuration de production (src/main/Java), il utilise le bean test principal (src/main/test) dans la configuration de test comme vous le souhaitez. (De toute évidence, je ne peux pas commenter le code chaque fois que je veux exécuter un test.)
À partir des journaux:
o.s.b.f.s.DefaultListableBeanFactory - Remplacer la définition de bean pour le bean 'sqsConnectionFactory' par une définition différente: remplacement [Root bean: class [null]; portée =; abstrait = faux; lazyInit = false; autowireMode = 3; dependencyCheck = 0; autowireCandidate = true; primary = true; factoryBeanName = testJmsConfiguration; factoryMethodName = sqsConnectionFactory; initMethodName = null; destroyMethodName = (déduit); défini dans la ressource de chemin de classe [com/foo/configuration/TestJmsConfiguration.class]]
avec
[Bean racine: classe [null]; portée =; abstrait = faux; lazyInit = false; autowireMode = 3; dependencyCheck = 0; autowireCandidate = true; primaire = faux; factoryBeanName = jmsConfiguration; factoryMethodName = sqsConnectionFactory; initMethodName = null; destroyMethodName = (déduit); défini dans la ressource de chemin de classe [com/foo/configuration/JmsConfiguration.class]]
Pourquoi Spring remplace-t-il un bean primaire par un bean non primaire et comment puis-je faire en sorte que Spring utilise le bean spécifiquement marqué comme bean primaire?
Edit: La configuration src/main/Java:
@Configuration
public class JmsConfiguration {
... other bean declarations here ...
@Bean
public SQSConnectionFactory sqsConnectionFactory(Region region) throws JMSException {
return SQSConnectionFactory.builder()
.withRegion(region)
.build();
}
}
La configuration de test:
@Configuration
public class TestJmsConfiguration {
@Bean(name="messageProducerMock")
public MessageProducer mockMessageProducer() {
return new MessageProducerMock();
}
... other bean declarations here ...
@Bean
@Primary
public SQSConnectionFactory sqsConnectionFactory(@Qualifier("messageProducerMock") MessageProducer messageProducerMock) throws JMSException {
... returning setup mock here
}
}
La classe avec les tests est annotée avec:
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles(profiles = {"test"})
@Primary
ne prend effet qu'au point d'injection, en cas de conflit car différents beans correspondent à la condition à injecter et une décision doit être prise.
@Primary
n'est pas utilisé lors de l'initialisation des beans. Comme vous utilisez deux méthodes différentes pour créer le même bean et que vous n'en nommez aucun, Spring considère que vous essayez de le remplacer, ce problème peut donc se produire. Un nom est la solution la plus simple, mais gardez à l'esprit que votre contexte initialisera toujours le bean que vous ne souhaitez pas utiliser.
Je pense que vous pourriez manquer @ContextConfiguration
dans votre classe de test.
Exemple de classe de configuration de test (src/test/Java/TestConfiguration.class):
@Configuration
@ComponentScan
public class TestConfiguration {
@Bean
RabbitSender rabbitSender() {
return mock(RabbitSender.class);
}
}
Exemple de classe de test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class SomeServiceTest {
}