0

Я модульное тестирование пружинного MVC контроллера в моем маленьком приложении, но получают следующее сообщение об ошибке:Ошибка модульного тестирование контроллеров Spring MVC призывающих REST API

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 вернулся через браузер и отобразился в моем угловом представлении, но модульный тест не работает. Ошибка java.lang.AssertionError: Ожидаемое состояние: < 200> но было: < 204>. 204 - ответ пуст ... Может быть>Инициализация Spring FrameworkServlet '' i.e. framework сервлет не инициализирован? Не уверен. Любая помощь будет оценена

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

Как выглядит контроллер, с которым вы тестируете? – Kejml

+0

Привет, Kejml, я обновил исходное сообщение с помощью контроллера. Спасибо – user2722614

+0

Хм, это может привести к сомнению. Очевидно, что ваш каталог CatalogueService возвращает пустой результат. Где служба берет данные? Какая-то база данных? Типичная настройка заключается в том, что обычный контекст использует отдельную базу данных из контекста тестирования (HSQL - популярный выбор для тестирования), поэтому вы должны убедиться, что тестовая база данных содержит некоторые данные тестирования. Это делается либо при запуске базы данных/при открытии соединения, либо в методах аннотирования @ Before/@ BeforeClass. – Kejml

ответ

0

Как видно из трассировки стека, тест не из-за ошибка утверждения: он ожидает HTTP-статус 200, но получает 204, который является HTTPStatus.NO_CONTENT, который вы возвращаете в контроллер, когда список i пусто.

 if(products.isEmpty()){ 
      return new ResponseEntity<List<Product>>(HttpStatus.NO_CONTENT); 
     } 

Если вы хотите, чтобы ваш контроллер возвращать 200 вам нужно CatalogueService издеваться, чтобы вернуть что-то ...

+0

Я обновил testRoot() в тестовом классе. Ответ был заполнен из жесткого кодированного списка. Я пробовал это много раз и омрачил его, мой плохой. Но, его все еще дало мне 204. – user2722614

+0

Вопросы есть: 'продукты' пустые, и если да, то почему ... И это то, что отладчик для ... – jny

0

В тесте, вы насмешливый ItemService (используя productServiceMock), но ваш контроллер вызов экземпляра CatalogueService

Также убедитесь, что ваши mocks правильно введены, отладчик действительно ваш лучший друг здесь. Я думаю, из вашего синтаксиса, что вы используете Mockito. В этом случае, изделенный объект имеет «$$ EnhancedByMockito» в своем методе getClass().getName()

+0

Его ItemService полностью.Это было просто опечатка, пытаясь быть осторожным! Сожалею! – user2722614

+0

Является ли макет инъекцией? Как я уже сказал, отладчик может сказать вам, что ... или использовать простой старый 'System.out.println()' – Kejml

+0

Следующая строка в ItemControllerTest заполняет mock >> when (productServiceMock.findCustomerProducts (1L)). ThenReturn (Массивы. asList (prod1, prod2)); Как я могу проверить, введен ли макет. Я новичок в тестировании, а потому глупые вопросы. – user2722614