在Spring Boot JUnit (objectMapper)中无法向集成测试方法发送请求体.writeValueA



我在Spring Boot JUnit中处理发送请求体到集成测试的问题。我收到了400个错误请求,而不是200个Ok。

下面是AdminRefreshTokenRequest

import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class AdminRefreshTokenRequest {
@NotBlank
private String refreshToken;
}

下面是refreshToken方法

@PostMapping("/refreshtoken")
public ResponseEntity<?> refreshToken(@RequestBody AdminRefreshTokenRequest refreshTokenRequest) {
.....
}

以下是集成测试方法的相关部分

@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
AdminRefreshTokenRequest refreshTokenRequest = AdminRefreshTokenRequest.builder()
.refreshToken("RefreshToken")
.build();
mockMvc.perform(post(ADMIN_CONTROLLER_BASEURL + "/refreshtoken")
.contentType("application/json")
.content(objectMapper.writeValueAsString(refreshTokenRequest)))
.andDo(print())
.andExpect(status().isOk())

我得到这个问题如下所示

MockHttpServletResponse:
Status = 400
Error message = null
Headers = [Content-Type:"application/problem+json"]
Content type = application/problem+json
Body = {"type":"about:blank","title":"Bad Request","status":400,"detail":"Failed to read request","instance":"/api/v1/refreshtoken"}
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status expected:<200> but was:<400>
Expected :200
Actual   :400

当mockMvc试图在我删除@RequestBody后调用该方法时,控制器的refreshToken方法中分配给refreshTokenRequest的值为null。

我该如何修复它?

解决方案如下:

在删除用于多个变量的@Builder后,我定义了@NoArgsConstructor@AllArgsConstructor。接下来,问题消失了。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdminRefreshTokenRequest {
@NotBlank
private String refreshToken;
}

问题是您的后端无法初始化请求体。默认情况下,框架做的是:

  1. 创建请求体的实例;
  2. 那么它将填充变量;
  3. 最后,它进入映射方法与构建的主体。

在第一步中,框架将调用你的主体类的空构造函数,所以如果它丢失了,它将返回一个400的错误代码。

要解决这个问题,您可以简单地替换@Builder@NoArgsConstructor在AdminRefreshTokenRequest类中。最后的主体类应该如下所示:
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class AdminRefreshTokenRequest {
@NotBlank
private String refreshToken;
}

这应该能解决问题,希望能有所帮助。