【问题标题】:SpringBoot Unit test - Service method is not invokedSpring Boot 单元测试 - 未调用服务方法
【发布时间】:2021-01-10 20:34:30
【问题描述】:

我是单元测试的新手。参考google后,我创建了一个Test类来测试我的Controller如下:

@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 响应

我在这里错过了什么?

【问题讨论】:

    标签: java spring-boot spring-boot-test


    【解决方案1】:

    使用@WebMvcTest时,spring boot只会初始化web层,不会加载完整的应用上下文。并且在使用@WebMvcTest时需要使用@MockBean来创建和注入mock。

    你做了什么

     @MockBean 
     PromoService promoService;
    

    Spring Boot 只实例化 web 层而不是整个上下文

    我们使用@MockBean 为 GreetingService 创建和注入一个 mock(如果不这样做,应用程序上下文将无法启动),我们使用 Mockito 设置它的期望。

    但是,因为它是模拟 bean,所以你有责任模拟 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);
            
    }
    

    【讨论】:

    • 谢谢!我看到你提到了 / 创建你想要返回的 PromoResponse 对象>>。但这不是硬编码我们的响应,而不是接收 POST 方法的实际响应。为什么需要对 PromoResponse 对象进行硬编码?
    • 既然你在模拟那个方法调用,你应该返回PromoResponse@Maha
    • 非常感谢@Deadpool
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 2021-03-15
    • 2021-09-23
    • 2016-05-28
    相关资源
    最近更新 更多