我想从我的
ResponseEntity
方法(子类)返回自定义 @Controller
。但是,在我的测试中反序列化时遇到困难。这是 MRE:
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
@RestController
@Slf4j
public class FallbackController {
@GetMapping("/fallback/{app-name}")
public Mono<CircuitBreakerFallbackMessage> getFallback(@PathVariable("app-name") String appName) {
return Mono.just(new CircuitBreakerFallbackMessage(appName));
}
@Getter
public static class CircuitBreakerFallbackMessage extends ResponseEntity<Map<String, String>> {
@JsonCreator
public CircuitBreakerFallbackMessage(String message) {
super(buildMessage(message), HttpStatus.GATEWAY_TIMEOUT);
}
private static Map<String, String> buildMessage(String appName) {
String message = MessageFormat.format("{0} is currently unavailable", appName);
HashMap<String, String> messageMap = new HashMap<>();
messageMap.put("message", message);
return messageMap;
}
}
}
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.http.HttpStatus;
import org.springframework.test.web.reactive.server.WebTestClient;
import java.text.MessageFormat;
import java.util.Map;
import java.util.regex.Pattern;
import static org.assertj.core.api.Assertions.assertThat;
@WebFluxTest(controllers = FallbackController.class)
class FallbackControllerTest {
@Autowired
WebTestClient testClient;
@Test
void testGetFallback() {
String appName = "some-app";
CircuitBreakerFallbackMessage fallbackMessage = testClient
.get()
.uri(MessageFormat.format("/fallback/{0}", appName))
.exchange()
.expectStatus().isEqualTo(HttpStatus.GATEWAY_TIMEOUT)
.expectBody(CircuitBreakerFallbackMessage.class) // it throws here
.returnResult()
.getResponseBody();
assertThat(fallbackMessage).isNotNull();
Map<String, String> fallbackMessageBody = fallbackMessage.getBody();
assertThat(fallbackMessageBody).isNotNull();
assertThat(fallbackMessage)
.extracting(fallbackMessageBody.get("message"))
.asString()
.containsPattern(Pattern.compile(appName + " (is )?(currently )?unavailable"));
}
}
<!--I won't include the entire pom, but you'd need these -->
<!-- Boot 3.2.1 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
结果:
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.example.dynamicgateway.controller.FallbackController$CircuitBreakerFallbackMessage` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (org.springframework.core.io.buffer.DataBufferInputStream); line: 1, column: 2]
我的错误是什么?
在同步应用程序中,如果没有任何
ResponseEntity
,@JsonCreator
反序列化不是很好吗?我认为课堂上缺少 Jackson 注释不应该成为问题
看起来您正在序列化为 JSON 对象,如下所示:
{ "message": "example message" }
但是用
@JsonCreator
注解的构造函数只有一个字符串参数。您可以尝试将构造函数更改为:
@JsonCreator
public CircuitBreakerFallbackMessage(@JsonProperty("message") String message)