Модульный тест SpringBoot — метод службы не вызывается

#java #spring-boot #spring-boot-test

#java #spring-boot #spring-boot-test

Вопрос:

Я новичок в модульном тестировании. После обращения к Google я создал тестовый класс для тестирования моего контроллера следующим образом:

 @RunWith(SpringRunner.class)
@WebMvcTest(PromoController.class)
public class PromoApplicationTests {
    @Autowired
    protected MockMvc mvc;
    @MockBean PromoService promoService;
   
   
   protected String mapToJson(Object obj) throws Exception {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsString(obj);
   }
   protected <T> T mapFromJson(String json, Class<T> clazz)
      throws JsonParseException, JsonMappingException, IOException {
      
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.readValue(json, clazz);
   }
   
   @Test
    public void applyPromotionTest_1() throws Exception {
           String uri = "/classPath/methodPath";
           List<Cart> cartLs = new ArrayList<Cart>();
          // added few objects to the list
           
           String inputJson = mapToJson(cartLs);
           MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
              .contentType(MediaType.APPLICATION_JSON).content(inputJson)).andReturn();
           
           int status = mvcResult.getResponse().getStatus();
           assertEquals(200, status);
           String actual = mvcResult.getResponse().getContentAsString();
           String expected = "{"key1":val1, "key2":"val 2"}";
           assertEquals(expected, actual, true);
            
    }
}
  

У меня есть следующий контроллер и класс обслуживания :

 @RequestMapping("/classPath")
@RestController
public class PromoController {
    @Autowired
    PromoService promoService;
    
    @PostMapping("/methodPath")
    public PromoResponse applyPromo(@RequestBody List<Cart> cartObj) {
        PromoResponse p = promoService.myMethod(cartObj);
        return p;
    }
}

@Component
public class PromoServiceImpl implements PromoService{

    @Override
    public PromoResponse myMethod(List<Cart> cartList) {
        // myCode
    }

}
  

Когда я отлаживал свой модульный тест, объект p в контроллере был нулевым.
Я получаю статус 200, но не ожидаемый ответ JSON

Чего мне здесь не хватает?

Ответ №1:

При использовании @WebMvcTest загрузка spring будет инициализировать только веб-уровень и не будет загружать полный контекст приложения. И вам нужно использовать @MockBean для создания и внедрения mock во время использования @WebMvcTest .

Что вы и сделали

  @MockBean 
 PromoService promoService;
  

Spring Boot создает экземпляр только веб-уровня, а не всего контекста

Мы используем @MockBean для создания и внедрения макета для GreetingService (если вы этого не сделаете, контекст приложения не сможет запуститься), и мы устанавливаем его ожидания с помощью Mockito.

Но, поскольку это макет компонента, вы несете ответственность за имитацию myMethod() вызова

 @Test
public void applyPromotionTest_1() throws Exception {
       String uri = "/classPath/methodPath";
       List<Cart> cartLs = new ArrayList<Cart>();
      // added few objects to the list

      // create PromoResponse object you like to return
      When(promoService.myMethod(ArgumentsMatchesr.anyList())).thenReturn(/*PromoResponse object */);
       
       String inputJson = mapToJson(cartLs);
       MvcResult mvcResult = mvc.perform(MockMvcRequestBuilders.post(uri)
          .contentType(MediaType.APPLICATION_JSON).content(inputJson)).andReturn();
       
       int status = mvcResult.getResponse().getStatus();
       assertEquals(200, status);
       String actual = mvcResult.getResponse().getContentAsString();
       String expected = "{"key1":val1, "key2":"val 2"}";
       assertEquals(expected, actual, true);
        
}
  

Комментарии:

1. Спасибо! Я вижу, что вы упомянули <<// создать объект PromoResponse, который вы хотите вернуть>> . Но разве это не было бы сложным кодированием нашего ответа вместо получения фактического ответа метода POST. Почему требуется жестко закодировать объект PromoResponse?

2. поскольку вы издеваетесь над этим вызовом метода, вы должны вернуть PromoResponse @Maha

3. Большое вам спасибо @Deadpool