2017-09-27 10 views
0

内の既存のBeanを拾うことができ、エラーをスローしていない私は、次のMavenベースのプロジェクト構造春ブーツの統合は、テスト別のmavenモジュール

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

を持っている私は希望product-serviceモジュールで書かれたMailClientServiceサービスがありますに統合テストをするのが好きです。統合テストは明らかにproduct-integration-testsモジュールに書かれています。

product-integration-testsモジュールのpomには、すでにproduct-web moduleが追加されています。

しかし、問題は、統合テストの実行中に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(製品統合テストの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(製品サービスのMavenモジュール)

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

}  

製品-ウェブ/の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

よく見ると、あなたがインスタンスを作成することができますMailClientServiceのインスタンスであるが、Springだけではは、@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 { 
... 

を私がどのように表示するには、これを編集しましたconfigクラスからモックを返すことができます。あなたの実装では、JavaMailSenderは自動で作成されますが、GreenMail変数は自動作成されません。

別の(おそらく単純オプション)Spring Boot testing doc (section 41.3.4)

+0

オクラホマで説明したように代わりにオートワイヤリングの@MockBeanアノテーションを使用することであろう、という考えを得ました。 MailClientServiceは他の2つのクラスを内部的に使用しているので、どのようにしてMailClientServiceを偽装できますか? – user2325154

関連する問題