我正在创建一个应用程序,我可以在其中创建汽车对象。 没有 setter 和 getter 的汽车类:
package github.KarolXX.demo.model;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime;
@Entity
@Table(name = "cars")
public class Car {
@Id
@GeneratedValue(generator = "inc")
@GenericGenerator(name = "inc", strategy = "increment")
private int id;
@NotBlank(message = "car name`s must be not empty")
private String name;
private LocalDateTime productionYear;
private boolean tested;
public Car() {
}
public Car(@NotBlank(message = "car name`s must be not empty") String name, LocalDateTime productionYear) {
this.name = name;
this.productionYear = productionYear;
}
}
我想知道如何在 Spring 中测试 POST 方法。下面是 POST 方法的代码片段,它只创建名为 Car 的 Java 对象(第一个片段)
@PostMapping("/cars")
ResponseEntity<Car> createCar(@RequestBody @Valid Car newCar) {
logger.info("Creating new car");
var result = repository.save(newCar);
return ResponseEntity.created(URI.create("/" + result.getId())).body(result);
}
我正在尝试以这种方式对其进行测试:
package github.KarolXX.demo.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import github.KarolXX.demo.TestConfiguration;
import github.KarolXX.demo.model.Car;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import java.time.LocalDateTime;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("integration")
class CarControllerIntegrationServerSideTest {
@Autowired
private MockMvc mockMvc;
@Test
public void httpPost_createsNewCar_returnsCreatedCar() throws Exception {
//given
Car car = new Car("second server side test", LocalDateTime.parse("2021-01-02T13:34:54"));
//when + then
mockMvc.perform(post("/cars")
.content(asJsonString(car))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isCreated());
}
public static String asJsonString(final Car objectCar) {
try {
return new ObjectMapper().writeValueAsString(objectCar);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
我是根据这个article 不幸的是我的测试没有通过。虽然在日志中我可以看到请求正文和请求标头设置正确,但我得到状态 400
2021-03-26 12:05:01.532 WARN 10696 --- [ main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Expected array or string.; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Expected array or string.
at [Source: (PushbackInputStream); line: 1, column: 59] (through reference chain: github.KarolXX.demo.model.Car["productionYear"])]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /cars
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"279"]
Body = {"id":0,"name":"second server side test","productionYear":{"month":"JANUARY","dayOfWeek":"SATURDAY","dayOfYear":2,"nano":0,"year":2021,"monthValue":1,"dayOfMonth":2,"hour":13,"minute":34,"second":54,"chronology":{"id":"ISO","calendarType":"iso8601"}},"tested":false,"brand":null}
Session Attrs = {}
Handler:
Type = github.KarolXX.demo.controller.CarController
Method = github.KarolXX.demo.controller.CarController#createCar(Car)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
MockHttpServletRequest:
HTTP Method = POST
Request URI = /cars
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"279"]
Body = {"id":0,"name":"second server side test","productionYear":{"month":"JANUARY","dayOfWeek":"SATURDAY","dayOfYear":2,"nano":0,"year":2021,"monthValue":1,"dayOfMonth":2,"hour":13,"minute":34,"second":54,"chronology":{"id":"ISO","calendarType":"iso8601"}},"tested":false,"brand":null}
Session Attrs = {}
Handler:
Type = github.KarolXX.demo.controller.CarController
Method = github.KarolXX.demo.controller.CarController#createCar(Car)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<201> but was:<400>
Expected :201
Actual :400
我不知道哪里出了问题,但是当我将这行代码 mockMvc.perform(post("/cars")
更改为这一行 mockMvc.perform(post("/")
时,我得到了状态 404
答案 0 :(得分:0)
我已经解决了这个问题,但我不知道为什么以前的版本不起作用。我从测试类中删除了静态方法并更改了 POST 方法检查:即我创建了一个将 JSON 作为字符串保存的变量并将其传递给 content
方法。在以前的版本中,此字符串由 ObjectMapper().writeValueAsString()
在静态方法中返回。我修改后的测试类:
@Test
public void httpPost_createsNewCar_returnsCreatedCar() throws Exception {
//given
//Car car = new Car("second server side test", LocalDateTime.parse("2021-01-02T13:34:54"));
String id = String.valueOf(repo.getSize());
String jsonString = new JSONObject()
.put("id", id)
.put("tested", false)
.put("productionYear", "2017-06-18T12:12:12")
.put("name", "Toyota")
.toString();
//when + then
mockMvc.perform(post("/cars")
.content(jsonString)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isCreated());
}