2017-09-27 2 views
0

J'ai la structure du projet basée maven-suivanteerreur de lancer de test d'intégration Boot printemps et pas en mesure de ramasser un haricot existant dans un autre module maven

product-app 
    product-web 
    product-service 
    product-integration-tests 

Il y a un service MailClientService écrit dans product-service module je voudrais aime faire un test d'intégration sur. Le test d'intégration est évidemment écrit dans le module product-integration-tests.

Le a déjà été ajouté en tant que dépendance dans le module product-integration-tests.

Cependant, le problème est que lors de l'exécution du test d'intégration, il n'est pas capable de construire le bean MailClientService et lance une exception d'exécution.

Exception

13:53:01.161 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.b[email protected]20b2475a] to prepare test instance [com[email protected]7857fe2] 
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.radial.hostedpayments.service.MailClientServiceIntegrationTest': Unsatisfied dependency expressed through field 'mailClientService': No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:385) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118) ~[spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83) ~[spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.boot.test.autoconfigure.AutoConfigureReportTestExecutionListener.prepareTestInstance(AutoConfigureReportTestExecutionListener.java:46) ~[spring-boot-test-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE] 
     at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12] 
     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12] 
     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12] 
     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12] 
     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12] 
     at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12] 
     at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) [spring-test-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:367) [surefire-junit4-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:274) [surefire-junit4-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238) [surefire-junit4-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:161) [surefire-junit4-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290) [surefire-booter-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242) [surefire-booter-2.19.1.jar:2.19.1] 
     at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121) [surefire-booter-2.19.1.jar:2.19.1] 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] 
     ... 30 more 
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.318 sec <<< FAILURE! - in com.radial.hostedpayments.service.MailClientServiceIntegrationTest 
shouldSendMail(com.radial.hostedpayments.service.MailClientServiceIntegrationTest) Time elapsed: 0.002 sec <<< ERROR! 
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.radial.hostedpayments.service.MailClientServiceIntegrationTest': Unsatisfied dependency expressed through field 'mailClientService': No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 


Results : 

Tests in error: 
    MailClientServiceIntegrationTest.shouldSendMail » UnsatisfiedDependency Error ... 

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0 

MailClientServiceIntegrationTest.java (essais d'intégration sous-produit module maven)

@RunWith(SpringRunner.class) 
public class MailClientServiceIntegrationTest { 

    @Autowired 
    private MailClientService mailClientService; 
    private GreenMail smtpServer; 

    @Before 
    public void setUp() throws Exception { 
     smtpServer = new GreenMail(new ServerSetup(25, null, "smtp")); 
     smtpServer.start(); 
    } 

    @Test 
    public void shouldSendMail() throws Exception { 
     //given 
     String recipient = "[email protected]"; 
     String message = "Test message content"; 
     //when 
     mailClientService.prepareAndSend(recipient, message); 
     //then 
     assertReceivedMessageContains(message); 
    } 

    private void assertReceivedMessageContains(String expected) throws IOException, MessagingException { 
     MimeMessage[] receivedMessages = smtpServer.getReceivedMessages(); 
     assertEquals(1, receivedMessages.length); 
     String content = (String) receivedMessages[0].getContent(); 
     assertTrue(content.contains(expected)); 
    } 

    @After 
    public void tearDown() throws Exception { 
     smtpServer.stop(); 
    } 

} 

MailClientService.java (module maven produit-service)

@Service 
public class MailClientService { 

    @Autowired 
    private JavaMailSender mailSender; 
    private MailContentBuilder mailContentBuilder; 

    @Value("${error.email.from.address}") 
    private String emailAddressFrom; 
    @Value("${error.email.to.address}") 
    private String emailRecipientAddress; 

    private String[] emailRecipientAddresses; 
    private static final boolean HTML_FLAG = true; 
    private static final String ERROR_ALERT_EMAIL_SUBJECT = "Hosted Payment Service - Error Alert on "; 
    private static final Logger LOGGER = LoggerFactory.getLogger(MailClientServiceImpl.class); 

    public MailClientServiceImpl(final JavaMailSender javaMailSender, final MailContentBuilder emailContentBuilder) { 
     this.mailSender = javaMailSender; 
     this.mailContentBuilder = emailContentBuilder; 
    } 

    @Override 
    public void prepareAndSend(final String message, final String emailSubject) { 
     emailRecipientAddresses = StringUtils.split(emailRecipientAddress, ','); 
     MimeMessagePreparator messagePreparator = mimeMessage -> { 
      MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage); 
      messageHelper.setFrom(emailAddressFrom); 
      messageHelper.setTo(emailRecipientAddresses); 
      if (StringUtils.isNotBlank(emailSubject)) { 
       messageHelper.setSubject(emailSubject); 
      } else { 
       messageHelper.setSubject(ERROR_ALERT_EMAIL_SUBJECT + CommonUtils.getHostName()); 
      } 

      // Create the HTML body using Thymeleaf 
      String htmlContent = mailContentBuilder.buildHtmlTemplating(message); 
      messageHelper.setText(htmlContent, HTML_FLAG); 
     }; 

     try { 
      // Send email 
      if (LOGGER.isDebugEnabled()) { 
       LOGGER.debug("Sending email '{}' to: {} ", ERROR_ALERT_EMAIL_SUBJECT, emailRecipientAddress); 
      } 
      mailSender.send(messagePreparator); 
     } catch (MailException e) { 
       e.printStackTrace(); 
       LOGGER.error("Problem with sending alert email to: {}, error message: {}", emailRecipientAddress, e.getMessage()); 
     } 
    } 

    @Override 
    public void prepareAndSend(final String message) { 
     prepareAndSend(message, null); 
    } 

}  

produit web/pom.xml

<plugin> 
    <groupId>org.apache.maven.plugins</groupId> 
    <artifactId>maven-war-plugin</artifactId> 
    <version>3.1.0</version> 
    <configuration> 
     <attachClasses>true</attachClasses> 
    </configuration> 
</plugin> 

produit-intégration-tests/pom.xml

<dependency> 
    <groupId>${project.groupId}</groupId> 
    <artifactId>hosted-payments</artifactId> 
    <version>${project.version}</version> 
    <classifier>classes</classifier> 
</dependency> 

Répondre

1

Si vous regardez attentivement, vous pouvez créer une instance de MailClientService, mais Spring ne peut pas simplement injecter une instance dans votre classe de test via l'annotation @Autowired:

No qualifying bean of type [com.radial.hostedpayments.service.MailClientService] found for dependency [com.radial.hostedpayments.service.MailClientService]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException 

Vous devez fournir des instances de bean Spring de votre classe MailClientService à votre classe de test. Cela peut être fait via l'annotation @ContextConfiguration.

Étape 1 - créer une classe @Configuration qui expose votre MailServiceClient:

@Configuration 
public class TestConfig { 

    @Bean 
    public JavaMailSender mailSender() { 
     // example of returning a mock object 
     return Mockito.mock(JavaMailSender.class); 
    }  

    @Bean 
    public GreenMail smtpServer() { 
     // another mock 
     return Mockito.mock(GreenMail.class); 
    } 

    @Bean 
    public MailClientService mailClientService(){ 
     // this could also be used to return a Mock object 
     return new MailClientService(); 
    } 
} 

Étape 2 - Ajouter la classe de configuration à votre test:

... 
@ContextConfiguration(classes = {TestConfig.class}) 
public class MailClientServiceIntegrationTest { 
... 

J'ai édité cela pour montrer comment vous pouvez renvoyer des simulacres de votre classe de configuration. Notez que dans votre implémentation, vous avez le nom automatique JavaMailSender, mais pas la variable GreenMail.

Une autre (probablement option plus simple) serait d'utiliser l'annotation @MockBean au lieu de autowiring comme décrit dans la Spring Boot testing doc (section 41.3.4)

+0

Ok, a eu l'idée. Pourriez-vous donner un exemple de comment puis-je me moquer du MailClientService puisqu'il utilise deux autres classes en interne? – user2325154