SpringBoot单元测试 – Service方法未被调用

huangapple go评论72阅读模式
英文:

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 &lt;T&gt; T mapFromJson(String json, Class&lt;T&gt; clazz)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, clazz);
}
@Test
public void applyPromotionTest_1() throws Exception {
String uri = &quot;/classPath/methodPath&quot;;
List&lt;Cart&gt; cartLs = new ArrayList&lt;Cart&gt;();
// 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 = &quot;{\&quot;key1\&quot;:val1, \&quot;key2\&quot;:\&quot;val 2\&quot;}&quot;;
assertEquals(expected, actual, true);
}
}

I have the following Controller and service Class :

@RequestMapping(&quot;/classPath&quot;)
@RestController
public class PromoController {
@Autowired
PromoService promoService;
@PostMapping(&quot;/methodPath&quot;)
public PromoResponse applyPromo(@RequestBody List&lt;Cart&gt; cartObj) {
PromoResponse p = promoService.myMethod(cartObj);
return p;
}
}
@Component
public class PromoServiceImpl implements PromoService{
@Override
public PromoResponse myMethod(List&lt;Cart&gt; 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 = &quot;/classPath/methodPath&quot;;
List&lt;Cart&gt; cartLs = new ArrayList&lt;Cart&gt;();
// 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 = &quot;{\&quot;key1\&quot;:val1, \&quot;key2\&quot;:\&quot;val 2\&quot;}&quot;;
assertEquals(expected, actual, true);
}

huangapple
  • 本文由 发表于 2020年9月24日 22:10:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/64048326.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定