使用 @WebMvcTest 进行单元测试 POST - @MockBean Service 返回 null

Gre*_*egg 5 spring unit-testing mocking spring-boot

我正在尝试对控制器进行单元测试以保存Brand实体。在此测试中,我创建了一个Brand希望返回的值,然后将 JSON 发布到控制器。最初,我依靠的是pass-by-reference我的控制器方法基本上是这样做的:

@Override
public ResponseEntity<MappingJacksonValue> save(@Valid @RequestBody Brand brand, BindingResult bindingResult) {

  validate(brand, null, bindingResult);
  if (bindingResult.hasErrors()) {
      throw new InvalidRequestException("Invalid Brand", bindingResult);
  }

  this.brandService.save(brand); // pass by reference
  MappingJacksonValue mappingJacksonValue = jsonView(JSON_VIEWS.SUMMARY.value, brand);
  return new ResponseEntity<>(mappingJacksonValue, HttpStatus.CREATED);
}
Run Code Online (Sandbox Code Playgroud)

请注意,我实际上并没有使用Brand从服务返回的内容。当我以这种方式测试时,我的测试失败了,因为控制器返回了我传入的 JSON,并且由于服务被模拟,控制器没有返回我期望的品牌,即有一个 ID。所以我改变了控制器来做到这一点:

brand = this.brandService.save(brand);
Run Code Online (Sandbox Code Playgroud)

但是,当我调试时,从模拟服务返回的品牌为空。下面是我的测试。

@RunWith(SpringRunner.class)
@WebMvcTest(BrandController.class)
public class BrandSimpleControllerTest {

  @Autowire
  private MockMvc mockMvc;

  @MockBean
  private BrandService brandService;

  @Test
  public void testSave() throws Exception {
    Brand brand = new Brand();
    brand.setId(1L);
    brand.setName("Test Brand");

    when(this.brandService.save(brand)).thenReturn(brand);

    this.mockMvc.perform(this.post("/api/brands")
      .content("{\"name\": \"Test Brand\"}"))
      .andExpect(jsonPath("$.id", is(1)))
      .andExpect(jsonPath("$.name", is("Test Brand")));
  }

}
Run Code Online (Sandbox Code Playgroud)

有什么建议么?

Gre*_*egg 5

好吧,问题解决了。问题是,您在服务调用中模拟的对象必须与传递到控制器中的对象相同,因此当模拟查看预期内容时,它会说“哦,您给了我这个,所以您想要那个”。这是使其工作的修改后的代码:

Brand brand = new Brand();
brand.setId(1L);
brand.setName("Test Brand");
brand.setDateCreated(new LocalDateTime());
brand.setLastUpdated(new LocalDateTime());

// since all I'm passing into the controller is a brand name...
when(this.brandService.save(new Brand("Test Brand"))).thenReturn(brand);
Run Code Online (Sandbox Code Playgroud)