英文:
SpringBoot Unit test - Service method is not invoked
问题
我是单元测试的新手。在参考了谷歌的资料后,我创建了一个测试类来测试我的控制器,如下所示:
@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 对象为 null。
我得到的状态码是 200,但预期的 JSON 响应并不是我期望的。
我在这里漏掉了什么?
英文:
I am new to Unit Testing. After referring google, I created a Test class to test my Controller as follows:
@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);
}
}
I have the following Controller and service Class :
@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
}
}
When I debugged my unit test, p object in the controller was null.
I am getting status as 200 but not the expected JSON response
What am I missing here?
答案1
得分: 4
在使用 @WebMvcTest 时,Spring Boot 仅会初始化 Web 层,而不会加载完整的应用程序上下文。您需要使用 @MockBean
在使用 @WebMvcTest
时创建和注入模拟对象。
您已经完成了以下操作:
@MockBean
PromoService promoService;
> Spring Boot 仅会实例化 Web 层,而不是整个上下文。
> 我们使用 @MockBean
为 GreetingService 创建和注入模拟对象(如果不这样做,应用程序上下文将无法启动),然后使用 Mockito 设置其预期行为。
然而,由于这是模拟对象,您需要自行模拟 myMethod()
调用:
@Test
public void applyPromotionTest_1() throws Exception {
String uri = "/classPath/methodPath";
List<Cart> cartLs = new ArrayList<Cart>();
// 向列表中添加一些对象
// 创建您想要返回的 PromoResponse 对象
when(promoService.myMethod(ArgumentMatchers.anyList())).thenReturn(/*PromoResponse 对象*/);
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);
}
英文:
While using @WebMvcTest spring boot will only initialize the web layer and will not load complete application context. And you need to use @MockBean
to create and inject mock while using @WebMvcTest
.
Which you have done
@MockBean
PromoService promoService;
>Spring Boot instantiates only the web layer rather than the whole context
> We use @MockBean to create and inject a mock for the GreetingService (if you do not do so, the application context cannot start), and we set its expectations using Mockito.
But the, since it is mock bean you are responsible to mock the myMethod()
call
@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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论