我在我的小应用程序中对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:预期的状态:&lt; 200&gt;但是:&lt; 204&gt;。 204 - 回复是空的...... 可以是&gt; 初始化Spring FrameworkServlet&#39; 即框架servlet未初始化?不确定。 任何帮助将不胜感激
My Rest Coontroller
@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);
}
}
答案 0 :(得分:0)
正如我们从堆栈跟踪中看到的那样,由于断言错误,测试失败:它期望HTTP状态200
,但得到204
,即HTTPStatus.NO_CONTENT
,您返回在列表为空时在控制器中。
if(products.isEmpty()){
return new ResponseEntity<List<Product>>(HttpStatus.NO_CONTENT);
}
如果您希望控制器返回200,则需要使用CatalogueService
模拟返回某些内容...
答案 1 :(得分:0)
In your test, you are mocking ItemService
(using productServiceMock
), but your controller is calling instance of CatalogueService
Also make sure your mocks are properly injected, debugger is really your best friend here. I guess from your syntax, that you are using Mockito. In such case, mocked object have "$$EnhancedByMockito" in their getClass().getName()
method