模拟方法 return 值在 Spring Boot @WebMvcTest 中为 null
Mocked method return value is null in Spring Boot @WebMvcTest
以下测试失败:org.json.JSONException: Unparsable JSON string
。
我尝试了模拟 saveAndFlush
方法
的各种变体
// doAnswer(returnsFirstArg()).when(this.shipwreckRepository).saveAndFlush(shipwreck);
// when(this.shipwreckRepository.saveAndFlush(shipwreck))
// .then(returnsFirstArg());
然而,同样的错误弹出并且 MockHttpServletResponse
body 为 null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
如何正确模拟存储库 saveAndFlush
方法 return 值?
SpringBootHomeControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest(ShipwreckController.class)
public class SpringBootShipwreckControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private ShipwreckRepository shipwreckRepository;
@Test
public void createShipwreck() throws Exception {
Shipwreck shipwreck = generateSampleShipwreck();
when(shipwreckRepository.saveAndFlush(shipwreck)).then(i -> i.getArgumentAt(0, Shipwreck.class));
ObjectMapper mapper = new ObjectMapper();
String shipwreckJson = mapper.writeValueAsString(shipwreck);
this.mvc.perform(post("/api/v1/shipwrecks")
.contentType(MediaType.APPLICATION_JSON)
.content(shipwreckJson)
)
.andExpect(status().isOk())
.andExpect(content().json(shipwreckJson));
verify(this.shipwreckRepository).saveAndFlush(shipwreck);
}
private Shipwreck generateSampleShipwreck() {
Integer depth = 10;
Double latitude = 1.0;
Double longitude = 1.0;
Integer yearDiscovered = 1;
String name = "name";
String description = "desc";
String condition = "cond";
Shipwreck shipwreck = new Shipwreck(1L, name, description, condition, depth, latitude, longitude, yearDiscovered);
return shipwreck;
}
}
ShipwreckRepository.java
public interface ShipwreckRepository extends JpaRepository<Shipwreck, Long> {
}
ShipwreckController.java
@RestController
@RequestMapping("/api/v1/")
public class ShipwreckController {
@Autowired
private ShipwreckRepository shipwreckRepository;
@RequestMapping(value = "shipwrecks", method = RequestMethod.POST)
public Shipwreck create(@RequestBody Shipwreck shipwreck) {
return shipwreckRepository.saveAndFlush(shipwreck);
}
}
Shipwreck.java
package com.boot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Shipwreck {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
String description;
String condition;
Integer depth;
Double latitude;
Double longitude;
Integer yearDiscovered;
public Shipwreck() { }
public Shipwreck(Long id, String name, String description, String condition, Integer depth, Double latitude, Double longitude, Integer yearDiscovered) {
this.id = id;
this.name = name;
this.description = description;
this.condition = condition;
this.depth = depth;
this.latitude = latitude;
this.longitude = longitude;
this.yearDiscovered = yearDiscovered;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public Integer getDepth() {
return depth;
}
public void setDepth(Integer depth) {
this.depth = depth;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Integer getYearDiscovered() {
return yearDiscovered;
}
public void setYearDiscovered(Integer yearDiscovered) {
this.yearDiscovered = yearDiscovered;
}
}
在 when() 和 verify() 指令中使用 Mockito.any() 而不是特定的 Shipwreck 实例。
您测试的控制器将接收的 Shipwreck 实例将不是您创建的实例,而是通过反序列化您调用它的 json 构建的新实例。因此,Mockito 不会响应指示使用前一个实例的指令。
备选方案:为 Shipwreck 定义适当的 equals() 和 hashCode() 方法。
以下测试失败:org.json.JSONException: Unparsable JSON string
。
我尝试了模拟 saveAndFlush
方法
// doAnswer(returnsFirstArg()).when(this.shipwreckRepository).saveAndFlush(shipwreck);
// when(this.shipwreckRepository.saveAndFlush(shipwreck))
// .then(returnsFirstArg());
然而,同样的错误弹出并且 MockHttpServletResponse
body 为 null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
如何正确模拟存储库 saveAndFlush
方法 return 值?
SpringBootHomeControllerTest.java
@RunWith(SpringRunner.class)
@WebMvcTest(ShipwreckController.class)
public class SpringBootShipwreckControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private ShipwreckRepository shipwreckRepository;
@Test
public void createShipwreck() throws Exception {
Shipwreck shipwreck = generateSampleShipwreck();
when(shipwreckRepository.saveAndFlush(shipwreck)).then(i -> i.getArgumentAt(0, Shipwreck.class));
ObjectMapper mapper = new ObjectMapper();
String shipwreckJson = mapper.writeValueAsString(shipwreck);
this.mvc.perform(post("/api/v1/shipwrecks")
.contentType(MediaType.APPLICATION_JSON)
.content(shipwreckJson)
)
.andExpect(status().isOk())
.andExpect(content().json(shipwreckJson));
verify(this.shipwreckRepository).saveAndFlush(shipwreck);
}
private Shipwreck generateSampleShipwreck() {
Integer depth = 10;
Double latitude = 1.0;
Double longitude = 1.0;
Integer yearDiscovered = 1;
String name = "name";
String description = "desc";
String condition = "cond";
Shipwreck shipwreck = new Shipwreck(1L, name, description, condition, depth, latitude, longitude, yearDiscovered);
return shipwreck;
}
}
ShipwreckRepository.java
public interface ShipwreckRepository extends JpaRepository<Shipwreck, Long> {
}
ShipwreckController.java
@RestController
@RequestMapping("/api/v1/")
public class ShipwreckController {
@Autowired
private ShipwreckRepository shipwreckRepository;
@RequestMapping(value = "shipwrecks", method = RequestMethod.POST)
public Shipwreck create(@RequestBody Shipwreck shipwreck) {
return shipwreckRepository.saveAndFlush(shipwreck);
}
}
Shipwreck.java
package com.boot.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Shipwreck {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;
String name;
String description;
String condition;
Integer depth;
Double latitude;
Double longitude;
Integer yearDiscovered;
public Shipwreck() { }
public Shipwreck(Long id, String name, String description, String condition, Integer depth, Double latitude, Double longitude, Integer yearDiscovered) {
this.id = id;
this.name = name;
this.description = description;
this.condition = condition;
this.depth = depth;
this.latitude = latitude;
this.longitude = longitude;
this.yearDiscovered = yearDiscovered;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public Integer getDepth() {
return depth;
}
public void setDepth(Integer depth) {
this.depth = depth;
}
public Double getLatitude() {
return latitude;
}
public void setLatitude(Double latitude) {
this.latitude = latitude;
}
public Double getLongitude() {
return longitude;
}
public void setLongitude(Double longitude) {
this.longitude = longitude;
}
public Integer getYearDiscovered() {
return yearDiscovered;
}
public void setYearDiscovered(Integer yearDiscovered) {
this.yearDiscovered = yearDiscovered;
}
}
在 when() 和 verify() 指令中使用 Mockito.any() 而不是特定的 Shipwreck 实例。
您测试的控制器将接收的 Shipwreck 实例将不是您创建的实例,而是通过反序列化您调用它的 json 构建的新实例。因此,Mockito 不会响应指示使用前一个实例的指令。
备选方案:为 Shipwreck 定义适当的 equals() 和 hashCode() 方法。