2017-09-27 26 views
0

我有以下的基于Maven的项目结构春季启动集成测试投掷的错误,不能够拿起一个现有的bean在另一个行家模块

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

有写在product-service模块的MailClientService服务,我会喜欢做一个集成测试。集成测试显然写在product-integration-tests模块中。

product-web module已被添加为product-integration-tests模块的pom中的依赖项。

但是,问题是,在集成测试的运行时期间,它无法构造MailClientService bean,并且正在抛出运行时异常。

异常

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(产品集成的测试行家模块)

@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(产品服务行家模块)

@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); 
    } 

}  

产品的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> 

产品集成的测试/ pom.xml的

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

回答

1

如果你仔细观察,你可以创建一个实例的邮件客户端服务,但春天不能通过@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 

您需要提供可用于您的测试类的MailClientService类的Spring bean实例。这可以通过@ContextConfiguration注释完成。

第1步 - 创建一个公开的MailServiceClient一个@Configuration类:

@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(); 
    } 
} 

第2步 - 配置类添加到您的测试:

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

我已经编辑这篇说明如何你可以从你的配置类返回模拟。请注意,在你的实现中,你有自动装配的JavaMailSender,但不是GreenMail变量。

另一个(可能更简单的选择)将作为Spring Boot testing doc (section 41.3.4)

+0

好的描述使用@MockBean注释,而不是自动装配,计上心来。你能否提供一个我如何模拟MailClientService的例子,因为它在内部使用两个其他的类? – user2325154

相关问题