问题
I am trying to create spring-mvc tests using Spring 3.2.1. Following some tutorials, I thought this would be straight-forward.
Here is my test:
@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( loader = AnnotationConfigContextLoader.class, classes = { JpaTestConfig.class } )
@WebAppConfiguration
public class HomeControllerTest {
@Resource
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
@Test
public void testRoot() throws Exception {
mockMvc.perform(get("/").accept(MediaType.TEXT_PLAIN)).andDo(print())
// print the request/response in the console
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.TEXT_PLAIN))
.andExpect(content().string("Hello World!"));
}
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
Here is my relevant pom.xml:
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.1.RELEASE</version>
</dependency>
I have the following test configuration class:
@Configuration
@EnableTransactionManagement
@ComponentScan( basePackages = { "com.myproject.service", "com.myproject.utility",
"com.myproject.controller" } )
@ImportResource( "classpath:applicationContext.xml" )
public class JpaTestConfig {
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
...
}
// various other services/datasource but not controllers
}
It is my understanding that adding @WebAppConfiguration
will force Spring to inject it. But when I run this test from within Eclipse I get:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.web.context.WebApplicationContext] found for dependency: 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.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:967) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:837) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:749) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
Update - I had to change my Test Java Configuration class
@Configuration
@EnableWebMvc
@ComponentScan( basePackages = { "...." } )
@EnableTransactionManagement
@ImportResource( "classpath:applicationContext.xml" )
public class JpaTestConfig extends WebMvcConfigurationSupport {
However, the problem is now that I can call my REST service, but it is invoking some other services, including database calls. What is the preferred way to just test the call and a mocked response. I would like to test valid and invalid conditions.
回答1:
In my case problem has been solved by replacing:
@ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { ... })
with
@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class, classes = { ... })
Notice the Web in the loader class name. With the previous loader, the GenericApplicationContext
has been injected despite @WebAppConfiguration
annotation.
回答2:
The below set-up uses only Java configuration classes and works fine for me.
@WebAppConfiguration
@ContextConfiguration(classes = TestApplicationContext.class)
public class MyClassTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@Before
public void setUp() {
mockMvc = webAppContextSetup(wac).build();
}
....
}
@Configuration
public class TestApplicationContext {
@Bean
public MyBean myBeanId(){
return Mockito.mock(MyBean.class);
}
....
}
The mere presence of @WebAppConfiguration on a test class ensures that a WebApplicationContext will be loaded for the test using a default path to the root of the web application. Therefore you can autowire the WebApplicationContext and use it to set up the mockMvc.
Note that the @WebAppConfiguration must be used in conjunction with @ContextConfiguration within the test class.
回答3:
Why don't you add this annotation and see if it works. Replace XXXX-text.xml with your bean mapping xml.
@ContextConfiguration(locations={"classpath:/XXXX-test.xml"})
回答4:
One of the tests is available for local dev support with annotation headers, where I had the similar issue from the question.
The comments are previous version of this test.
@RunWith(SpringJUnit4ClassRunner.class)
/* @EnableJpaAuditing */ /* for jpa dates */ /* it should be defined only once,
because 'jpaAuditingHandler' defined in null on application startup */
@EntityScan(basePackageClasses = { EnableJpaAuditing.class, Jsr310JpaConverters.class })
//@ProfileValueSourceConfiguration(Application.class)
//@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
//@PropertySource("classpath:application.properties")
@TestPropertySource(locations = "classpath:application.properties")
//@WebAppConfiguration
@SpringBootTest
public class JpaTests {/* */}
来源:https://stackoverflow.com/questions/16136376/webappconfiguration-not-injected