java - Spring Cloud Contract LocalDateTime 断言失败

标签 java spring spring-boot localdate contract

最后一天,我一直在 Spring 契约(Contract)测试中与 LocalDateTime 作斗争。

基类:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public abstract class VennotenDossiersConsumerBase {

@Autowired
private OptInController optInController;

@Autowired
private ActieLogController actieLogController;

@MockBean
private OptInService optInService;

@MockBean
private ActieLogService actieLogService;

@BeforeEach
public void setup() throws IOException {
    String liantisId = "liantisId";
    String applicatieNaam = "applicatieNaam";
    String gebruikerId = "gebruikerId";
    String optInGebruikerId = "optInGebruikerId";

    StandaloneMockMvcBuilder standaloneMockMvcBuilder
            = MockMvcBuilders.standaloneSetup(optInController, actieLogController);
    RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder);

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(new JavaTimeModule());

    OptIn createOptIn = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/registerOptInRequestBody.json"), OptIn.class);
    OptIn getOptIn = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getOptInResponseBody.json"), OptIn.class);
    List<OptIn> getOptInByLiantisId = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getOptInByLiantisIdResponseBody.json"), new TypeReference<List<OptIn>>() {});
    List<OptIn> getAllOptIns = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getAllOptInsResponseBody.json"), new TypeReference<List<OptIn>>() {});
    List<ActieLog> getAllActionLogs = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getAllActionLogsResponseBody.json"), new TypeReference<List<ActieLog>>() {});
    List<ActieLog> getActionLogsByLiantisId = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getActionLogsByLiantisIdResponseBody.json"), new TypeReference<List<ActieLog>>() {});
    List<ActieLog> getActionLogsByGebruikerId = objectMapper.readValue(new File("src/test/resources/contracts/vennotenDossiersConsumer/getActionLogsByGebruikerIdResponseBody.json"), new TypeReference<List<ActieLog>>() {});

    when(optInService.createOptIn(any(OptIn.class))).thenReturn(createOptIn);
    when(optInService.getOptIn(liantisId, applicatieNaam, optInGebruikerId)).thenReturn(getOptIn);
    when(optInService.getAllOptIns()).thenReturn(getAllOptIns);
    when(optInService.getOptInsByLiantisId(liantisId)).thenReturn(getOptInByLiantisId);
    when(actieLogService.getAllActionLogs()).thenReturn(getAllActionLogs);
    when(actieLogService.getActionLogsByLiantisId(liantisId)).thenReturn(getActionLogsByLiantisId);
    when(actieLogService.getActionLogsByGebruikerId(gebruikerId)).thenReturn(getActionLogsByGebruikerId);
}
}

常规脚本:

Contract.make {
description "should return an Action Log for GebruikerId"
request{
    url("api/actionlogs") {
        headers {
            contentType(applicationJson())
        }
        queryParameters {
            parameter("gebruikerId","gebruikerId")
        }
    method GET()
    }
}
response {
    status OK()
    headers {
        contentType(applicationJson())
    }
    body(file("getActionLogsByGebruikerIdResponseBody.json"))
}
}

ResponseBody.json:

[
{
"liantisId": "liantisId1",
"entiteitActie": "prospect",
"applicatieNaam": "applicatieNaam1",
"actie": "CREATE",
"optInGebruiker": {
  "gebruikerId": "gebruikerId",
  "username": "username1",
  "qualificatie": "qualificatie1"
},
"actionLoggedDate": "2020-03-02T09:54:10.758"
}
]

生成的测试:

public class VennotenDossiersConsumerTest extends VennotenDossiersConsumerBase {

@Test
public void validate_getActionLogsByGebruikerId() throws Exception {
    // given:
        MockMvcRequestSpecification request = given()
                .header("Content-Type", "application/json");

    // when:
        ResponseOptions response = given().spec(request)
                .queryParam("gebruikerId","gebruikerId")
                .get("api/actionlogs");

    // then:
        assertThat(response.statusCode()).isEqualTo(200);
        assertThat(response.header("Content-Type")).matches("application/json.*");

    // and:
        DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
        assertThatJson(parsedJson).array().contains("['liantisId']").isEqualTo("liantisId1");
        assertThatJson(parsedJson).array().contains("['entiteitActie']").isEqualTo("prospect");
        assertThatJson(parsedJson).array().contains("['applicatieNaam']").isEqualTo("applicatieNaam1");
        assertThatJson(parsedJson).array().contains("['actie']").isEqualTo("CREATE");
        assertThatJson(parsedJson).array().field("['optInGebruiker']").field("['gebruikerId']").isEqualTo("gebruikerId");
        assertThatJson(parsedJson).array().field("['optInGebruiker']").field("['username']").isEqualTo("username1");
        assertThatJson(parsedJson).array().field("['optInGebruiker']").field("['qualificatie']").isEqualTo("qualificatie1");
        assertThatJson(parsedJson).array().contains("['actionLoggedDate']").isEqualTo("2020-03-02T09:54:10.758");
}

运行测试时出现错误:

java.lang.IllegalStateException: Parsed JSON [[{"liantisId":"liantisId","entiteitActie":"prospect","applicatieNaam":"applicatieNaam1","actie":"CREATE","optInGebruiker":{"gebruikerId":"gebruikerId1","username":"username1","qualificatie":"qualificatie1"},"actionLoggedDate":[2020,3,2,9,54,10,758000000]}]] doesn't match the JSON path [$[*][?(@.['actionLoggedDate'] == '2020-03-02T09:54:10.758')]]

    at com.toomuchcoding.jsonassert.JsonAsserter.check(JsonAsserter.java:228)
    at com.toomuchcoding.jsonassert.JsonAsserter.checkBufferedJsonPathString(JsonAsserter.java:267)
    at com.toomuchcoding.jsonassert.JsonAsserter.isEqualTo(JsonAsserter.java:101)
    at be.liantis.gdpr.service.contracts.VennotenDossiersConsumerTest.validate_getActionLogsByLiantisId(VennotenDossiersConsumerTest.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:220)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:188)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:202)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:181)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)

因此,当在生成的测试中执行 get 请求时,它会以数组形式返回 localDateTime。 我一直在尝试将自定义 ObjectMappers 分配给 RestAssuredMockMVC 但没有任何效果。

如果我使用

RestAssuredMockMvc.config().objectMapperConfig(ObjectMapperConfig.objectMapperConfig().jackson2ObjectMapperFactory((type, s) -> OBJECT_MAPPER));

这不起作用。

如果我将它作为参数传递给standaloneSetup(),也不起作用。

我也尝试过mockMVC消息转换器,也不起作用。

以前有人遇到过这个问题吗? 我也找不到任何使用 LOCALDATE 或 LOCALDATETIME 的 Spring 合约示例。

不包含 localDateTime 的测试成功,没有任何问题。

有人知道该怎么做吗?

最佳答案

我自己解决了这个问题,我已经停止使用独立设置。

我给了 RestAssured 我的 webappcontext,然后它使用了正确的对象映射器。

RestAssuredMockMvc.webAppContextSetup(appContext)

其中 appContext 是我的 Autowired WebApplicationContext:

@Autowired
private WebApplicationContext appContext;

为了绕过由于安全上下文而出现的 401,我在基类上使用了 @WithMockUser。

@WithMockUser
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public abstract class VennotenDossiersConsumerBase

关于java - Spring Cloud Contract LocalDateTime 断言失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60550853/

相关文章:

java - 从 docker 镜像运行 Maven 命令

java - 并行运行 JUnit5 测试但希望保留一些测试顺序

spring - Hibernate SessionFactory 与 Spring LocalSessionFactoryBean

spring-boot - 如何在新的grails 3应用程序中使用现有的web.xml?

java - 通过代码访问 Facebook

Java - 绘制动态形状轮廓

java - 表单对象的 id 被设置为 0

java - Spring REST Controller 未映射

spring - @Transaction 使我的 REST 端点消失

spring - 更改分支后无法解决Flyway依赖性