2017-05-07 89 views
1

我有一个基本的SpringBoot应用程序,嵌入式Tomcat,Thymeleaf模板引擎,以及封装为可执行JAR文件。Spring Boot中的WebMvcTest

我有这个类:

@Service 
public class I18NService { 

    /** The application logger */ 
    private static final Logger LOG = LoggerFactory.getLogger(I18NService.class); 

    @Autowired 
    private MessageSource messageSource; 

    ... 
} 

该控制器

@Controller 
public class ForgotMyPasswordController extends TdkController { 


    @Autowired 
    private I18NService i18NService; 

    @Autowired 
    private EmailService emailService; 

... 
} 

启动应用程序正常工作,该试验也可以正常使用

public class ForgotMyPasswordControllerTests { 

    private ForgotMyPasswordController controller; 

    @Before 
    public void setUp() throws Exception { 
     controller = new ForgotMyPasswordController(); 
    } 


    @Test 
    public void testHandleListRequest() { 
     assertEquals("forgotmypassword/emailForm", controller.forgotPasswordGet()); 
    } 

} 

但是当我运行这个:

@RunWith(SpringRunner.class) 
@WebAppConfiguration 
@WebMvcTest 
public class MockMvcTests { 

    // Pull in the application context created by @ContextConfiguration 
    @Autowired 
    private WebApplicationContext wac; 

    private MockMvc mockMvc; 

    @Before 
    public void setup() { 
     // Setup MockMVC to use our Spring Configuration 
     this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 
    } 


    @Test 
    public void getDeviceEventsTest() throws Exception { 
     this.mockMvc 
       .perform(get("/forgotmypassword") // 
         .accept(MediaType.parseMediaType("text/html;charset=UTF-8"))) 
       .andExpect(status().isOk()) // 
       .andExpect(model().size(0)); // 

    } 
} 

我得到这个错误:

16486 [main] ERROR o.s.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [or[email protected]5876a9af] to prepare test instance [[email protected]] 
java.lang.IllegalStateException: Failed to load ApplicationContext 
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) 
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) 
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189) 
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131) 
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'forgotMyPasswordController': Unsatisfied dependency expressed through field 'i18NService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.tdk.web.i18n.I18NService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) 
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) 
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) 
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) 
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) 
    ... 25 common frames omitted 
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.tdk.web.i18n.I18NService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) 
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585) 
    ... 43 common frames omitted 
+0

WebMvcTest的整点只是加载MVC组件。其他组件必须被嘲笑。阅读文档:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests –

+0

@JBNizet,请转换为答案 –

回答

3

WebMvcTest的整点是只装载MVC组件。其他组件必须被嘲笑。阅读the documentation

To test Spring MVC controllers are working as expected you can use the @WebMvcTest annotation. @WebMvcTest will auto-configure the Spring MVC infrastructure and limit scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Filter, WebMvcConfigurer and HandlerMethodArgumentResolver. Regular @Component beans will not be scanned when using this annotation.

Often @WebMvcTest will be limited to a single controller and used in combination with @MockBean to provide mock implementations for required collaborators.