【发布时间】:2016-01-31 06:05:57
【问题描述】:
我在我的小应用程序中对 Spring MVC 控制器进行单元测试,但出现以下错误:
INFO: **Initializing Spring FrameworkServlet ''**
Oct 30, 2015 5:37:38 PM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization started
Oct 30, 2015 5:37:38 PM org.springframework.test.web.servlet.TestDispatcherServlet initServletBean
INFO: FrameworkServlet '': initialization completed in 2 ms
Running com.sky.testmvc.product.controller.ProductSelectionControllerTest
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.031 sec <<< FAILURE!
testRoot(com.sky.testmvc.product.controller.ProductSelectionControllerTest) Time elapsed: 0.031 sec <<< FAILURE!
*java.lang.AssertionError: **Status expected:<200> but was:<204>***
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:549)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141)
其余控制器如下:
@RestController
public class ItemRestController {
@Autowired
ItemService catalogueService;
@Autowired
LocationService locationService;
@RequestMapping(value = "/product/{customerId}", produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET)
public ResponseEntity<List<Item>> listCustomerProducts(@PathVariable("customerId") int customerId) {
Integer customerLocation=(Integer) locationService.findLocationByCustomerId(customerId);
List<Product> products = catalogueService.findCustomerProducts(customerLocation);
if(products.isEmpty()){
return new ResponseEntity<List<Product>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Product>>(products, HttpStatus.OK);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {TestContext.class, AppConfiguration.class}) //load your mvc config classes here
public class ItemControllerTest {
private MockMvc mockMvc;
@Autowired
private ItemService productServiceMock;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
Mockito.reset(productServiceMock);
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testRoot() throws Exception
{
Product prod1= new Product(1L,"Orange", new ProductCategory(1,"Sports"),new CustomerLocation(2,"London"));
Product prod2= new Product(2L,"Banana", new ProductCategory(1,"Sports"),new CustomerLocation(2,"London"));
when(productServiceMock.findCustomerProducts(1L)).thenReturn(Arrays.asList(prod1, prod2));
mockMvc.perform(get("/product/{id}", 1L))
.andExpect(status().isOk())
.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].productId", is(1)))
.andExpect(jsonPath("$[0].productName", is("Orange")))
.andExpect(jsonPath("$[1].productId", is(2)))
.andExpect(jsonPath("$[1].productName", is("Banana")));
verify(productServiceMock, times(1)).findCustomerProducts(1L);
verifyNoMoreInteractions(productServiceMock);
}
}
请参阅下面的 TestContext:
@Configuration
public class TestContext {
private static final String MESSAGE_SOURCE_BASE_NAME = "i18n/messages";
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename(MESSAGE_SOURCE_BASE_NAME);
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
@Bean
public ItemService catalogueService() {
return Mockito.mock(ItemService .class);
}
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.uk.springmvc")
public class AppConfiguration extends WebMvcConfigurerAdapter{
private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/views/";
private static final String VIEW_RESOLVER_SUFFIX = ".jsp";
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix(VIEW_RESOLVER_PREFIX);
viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX);
registry.viewResolver(viewResolver);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public SimpleMappingExceptionResolver exceptionResolver() {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
Properties exceptionMappings = new Properties();
exceptionMappings.put("java.lang.Exception", "error/error");
exceptionMappings.put("java.lang.RuntimeException", "error/error");
exceptionResolver.setExceptionMappings(exceptionMappings);
Properties statusCodes = new Properties();
statusCodes.put("error/404", "404");
statusCodes.put("error/error", "500");
exceptionResolver.setStatusCodes(statusCodes);
return exceptionResolver;
}
}
如前所述,应用程序工作正常,我可以读取通过浏览器返回的 json 并将其显示在我的 angularjs 视图中,但单元测试不起作用。错误是 java.lang.AssertionError:预期状态: 但原为:。 204 - 响应为空... 可能是 > Initializing Spring FrameworkServlet '' 即框架 servlet 未初始化?不确定。 任何帮助将不胜感激
我的休息控制器
@RestController 公共类 ItemRestController {
@Autowired
ItemService catalogueService; //Service which will do product retrieval
@Autowired
LocationService locationService; //Service which will retrieve customer location id using customer id
//-------------------Retrieve All Customer Products--------------------------------------------------------
@RequestMapping(value = "/product/{customerId}", produces = {MediaType.APPLICATION_JSON_VALUE}, method = RequestMethod.GET)
public ResponseEntity<List<Product>> listCustomerProducts(@PathVariable("customerId") int customerId) {
Integer customerLocation=(Integer) locationService.findLocationByCustomerId(customerId);
List<Product> products = catalogueService.findCustomerProducts(customerLocation);
if(products.isEmpty()){
return new ResponseEntity<List<Product>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<List<Product>>(products, HttpStatus.OK);
}
}
【问题讨论】:
-
你测试的控制器长什么样?
-
嗨 Kejml,我已经用控制器更新了原始帖子。谢谢
-
嗯,这可能会导致很长的问题。显然,您的目录 CatalogueService 返回空结果。服务从哪里获取数据?某种数据库?典型的设置是,普通上下文使用与测试上下文不同的数据库(HSQL 是测试的流行选择),因此您必须确保测试数据库包含一些测试数据。这是在数据库启动/打开连接时或在测试的 @Before/@BeforeClass 注释方法中完成的
-
或者你可以模拟服务,这取决于你是进行单元测试还是集成测试......
-
我已经更新了测试类中的 testRoot()。响应是从硬编码列表中填充的。我已经尝试过很多次并忽略了它,我的错。但是,它仍然给了我一个 204。
标签: spring spring-mvc spring-restcontroller spring-mvc-test