Citrus Framework - SUT 与其他服务通信的问题

Citrus Framework - Problem with SUT communicating with other services

我有一组通过 Spring Boot 实现的微服务,它们通过 HTTP REST 进行通信。我正在尝试使用 Citrus Framework 设置集成测试。我已经成功地为一些服务编写并执行了集成测试,但我正在努力应对更复杂的用例。

场景如下:

我有一个概念性的 "mission planning" 应用程序,它涉及 3 个服务:任务规划器、路线生成器和路线评估器。任务规划器调用这 2 个路由服务来执行规划任务所需的一些工作。路由服务不进行 REST 调用。

我已经将我的 Maven POM 文件设置为 运行 在执行 Maven 验证步骤时的集成测试。故障安全和 Spring Boot maven 插件被配置为执行此操作。

路线服务的集成测试按预期工作,但任务规划器的测试没有。我怀疑一个可能的原因是路由服务还没有启动。因此,经过一些研究,我在集成测试逻辑中插入调用以在进行测试工作之前启动这 2 个服务,并在之后停止它们。

我不是 100% 确定我是否采取了正确的步骤来正确启动服务。我也很好奇是否有办法知道他们是否真的启动成功了。我找不到解决此问题的任何文档。

无论如何,要么它们没有启动,要么它们的配置有问题,要么有其他原因导致问题。当我 运行 测试时,它失败并指示任务规划器无法连接到路线生成器(首先调用)。

以下是网络详细信息:

我的工作场所确实使用 HTTP 代理 - 这会影响本地主机通信吗?

任务规划器

EndpointConfig.java:

@Configuration
public class EndpointConfig {
  @Bean
  public HttpClient missionPlannerHTTPClient() {
    return CitrusEndpoints.http().client().requestUrl("http://localhost:9100").build();
  }
  @Bean
  public Server routeGeneratorServer() {
    return CitrusEndpoints.http().server().port(9110).timeout(10000).build();
  }
  @Bean
  public Server routeAssessorServer() {
    return CitrusEndpoints.http().server().port(9120).timeout(10000).build();
  }
}

我有限的理解是这些 bean 应该在指定的端口上提供 HTTP 服务器 运行ning。 不过,对于我来说,一个巨大的未知数是我如何真正获得 运行 的相应服务?我如何将它们与这些端点相关联?

我应该 "mocking" 路线服务吗?我假设我会做如下事情:

[柑橘框架用户指南的片段https://citrusframework.org/citrus/reference/2.8.0/html/index.html#http-rest-server]

http().server("helloHttpServer")
          .receive()
          .post("/test")
          .payload("<testRequestMessage>" +
                    "<text<Hello HttpServer</text>" +
                  "</testRequestMessage>")
          .contentType("application/xml")
          .accept("application/xml, */*")
          .header("X-CustomHeaderId", "${custom_header_id}")
          .header("Authorization", "Basic c29tZVVzZXJuYW1lOnNvbWVQYXNzd29yZA==")
          .extractFromHeader("X-MessageId", "message_id");
http().server("helloHttpServer")
          .send()
          .response(HttpStatus.OK)
          .payload("<testResponseMessage>" +
                    "<text<Hello Citrus</text>" +
                  "</testResponseMessage>")
          .version("HTTP/1.1")
          .contentType("application/xml")
          .header("X-CustomHeaderId", "${custom_header_id}")
          .header("X-MessageId", "${message_id}");

完全不确定我实际需要多少这里显示的所有内容。我不明白这两个电话的最后部分。

模拟非 SUT 服务对于某些形式的测试是有意义的,但是我将如何进行端到端测试,其中给定使用链中的所有服务都是真实的?

MissionPlannerIT.java:

public class MissionPlannerIT extends JUnit4CitrusTest {

  @Qualifier("routeGeneratorServer")
  private HttpServer routeGeneratorServer;
  @Qualifier("routeAssessorServer")
  private HttpServer routeAssessorServer;

  @Autowired
  private HttpClient missionPlannerHTTPClient;

  @Test
  @CitrusTest
  // @formatter:off
  public void testPlanMission(@CitrusResource TestRunner runner) {
    runner.description("Test mission planning 'plan mission' REST endpoint");

    // Start route generator and route assessor.
    runner.start(routeGeneratorServer);
    runner.start(routeAssessorServer);

    // Call mission planner to plan a mission.
    // Note: There is no request body (payload).
    runner.http(builder -> builder
        .client(missionPlannerHTTPClient)
        .send()
        .post("/v1/missionServices/missionPlanning/planMission"));

    // Expect a success response.
    runner.http(builder -> builder
        .client(missionPlannerHTTPClient)
        .receive()
        .response(HttpStatus.OK)
        .messageType(MessageType.JSON)
        .payload(new ClassPathResource("templates/plan-mission-response.json")));

    // Shut down route services.
    runner.stop(routeGeneratorServer);
    runner.stop(routeAssessorServer);
  }
  // @formatter:on

}

我不清楚为什么这 2 个服务器用 @Qualifier 注释而不是 @Autowired

pom.xml:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <configuration>
      <systemProperties>
        <system.under.test.mode>${system.under.test.mode}</system.under.test.mode>
      </systemProperties>
    </configuration>
    <executions>
      <execution>
        <id>integration-tests</id>
        <goals>
          <goal>integration-test</goal>
          <goal>verify</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
      <mainClass>edu.mit.ll.mission_services.service.mission_planner.ApplicationMain</mainClass>
      <useTestClasspath>false</useTestClasspath>
    </configuration>
    <executions>
      <execution>
        <id>pre-integration-test</id>
        <goals>
          <goal>start</goal>
        </goals>
      </execution>
      <execution>
        <id>post-integration-test</id>
        <goals>
          <goal>stop</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

控制台日志:

$ mvn verify
...
[INFO] --- spring-boot-maven-plugin:2.1.6.RELEASE:start (pre-integration-test) @ mission-planner ---
...

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.6.RELEASE)

[INFO]
[INFO] --- maven-failsafe-plugin:2.22.2:integration-test (default) @ mission-planner ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT
[WARNING]
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:9110/v1/missionServices/missionPlanning/generateRoute": Connect to localhost:9110 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect; nested exception is org.apache.http.conn.HttpHostConnectException: Connect to localhost:9110 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
    at org.springframework.web.client.RestTemplate.doExecute (RestTemplate.java:744)
    at org.springframework.web.client.RestTemplate.execute (RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForEntity (RestTemplate.java:445)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.postGenerateRoute (MissionPlanner.java:210)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.planMission (MissionPlanner.java:143)
    at edu.mit.ll.mission_services.service.mission_planner.controller.MissionPlannerController$Runner.executeTask (MissionPlannerController.java:51)
    at edu.mit.ll.mission_services.common.util.ITask.run (ITask.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:624)
    at java.lang.Thread.run (Thread.java:748)
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:9110 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect (DefaultHttpClientConnectionOperator.java:156)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect (PoolingHttpClientConnectionManager.java:374)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute (MainClientExec.java:393)
    at org.apache.http.impl.execchain.MainClientExec.execute (MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute (ProtocolExec.java:186)
    at org.apache.http.impl.execchain.RetryExec.execute (RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute (RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute (InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute (CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute (CloseableHttpClient.java:56)
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal (HttpComponentsClientHttpRequest.java:87)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal (AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute (AbstractClientHttpRequest.java:53)
    at org.springframework.web.client.RestTemplate.doExecute (RestTemplate.java:735)
    at org.springframework.web.client.RestTemplate.execute (RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForEntity (RestTemplate.java:445)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.postGenerateRoute (MissionPlanner.java:210)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.planMission (MissionPlanner.java:143)
    at edu.mit.ll.mission_services.service.mission_planner.controller.MissionPlannerController$Runner.executeTask (MissionPlannerController.java:51)
    at edu.mit.ll.mission_services.common.util.ITask.run (ITask.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:624)
    at java.lang.Thread.run (Thread.java:748)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect (Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect (DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect (AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress (AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect (AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect (PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect (SocksSocketImpl.java:392)
    at java.net.Socket.connect (Socket.java:589)
    at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket (PlainConnectionSocketFactory.java:75)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect (DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect (PoolingHttpClientConnectionManager.java:374)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute (MainClientExec.java:393)
    at org.apache.http.impl.execchain.MainClientExec.execute (MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute (ProtocolExec.java:186)
    at org.apache.http.impl.execchain.RetryExec.execute (RetryExec.java:89)
    at org.apache.http.impl.execchain.RedirectExec.execute (RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute (InternalHttpClient.java:185)
    at org.apache.http.impl.client.CloseableHttpClient.execute (CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute (CloseableHttpClient.java:56)
    at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal (HttpComponentsClientHttpRequest.java:87)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal (AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute (AbstractClientHttpRequest.java:53)
    at org.springframework.web.client.RestTemplate.doExecute (RestTemplate.java:735)
    at org.springframework.web.client.RestTemplate.execute (RestTemplate.java:670)
    at org.springframework.web.client.RestTemplate.postForEntity (RestTemplate.java:445)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.postGenerateRoute (MissionPlanner.java:210)
    at edu.mit.ll.mission_services.service.mission_planner.service.MissionPlanner.planMission (MissionPlanner.java:143)
    at edu.mit.ll.mission_services.service.mission_planner.controller.MissionPlannerController$Runner.executeTask (MissionPlannerController.java:51)
    at edu.mit.ll.mission_services.common.util.ITask.run (ITask.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:624)
    at java.lang.Thread.run (Thread.java:748)
09:00:46.576 [main] ERROR com.consol.citrus.report.LoggingReporter - TEST FAILED MissionPlannerIT.testPlanMission <edu.mit.ll.mission_services.service.mission_planner> Nested exception is:
com.consol.citrus.exceptions.TestCaseFailedException: Failed to validate JSON text:
{"timestamp":"2020-02-06T14:00:46.436+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"} Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at com.consol.citrus.TestCase.executeAction(TestCase.java:227) [citrus-core-2.8.0.jar:?]
        at com.consol.citrus.dsl.runner.DefaultTestRunner.run(DefaultTestRunner.java:188) ~[citrus-java-dsl-2.8.0.jar:?]
        at com.consol.citrus.dsl.runner.DefaultTestRunner.http(DefaultTestRunner.java:540) [citrus-java-dsl-2.8.0.jar:?]
        at edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT.testPlanMission(MissionPlannerIT.java:44) ~[test-classes/:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_191]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_191]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_191]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_191]
        at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at com.consol.citrus.dsl.junit.JUnit4CitrusTest.invokeTestMethod(JUnit4CitrusTest.java:99) [citrus-java-dsl-2.8.0.jar:?]
        at com.consol.citrus.dsl.junit.JUnit4CitrusTest.run(JUnit4CitrusTest.java:70) [citrus-java-dsl-2.8.0.jar:?]
        at com.consol.citrus.junit.CitrusJUnit4Runner$InvokeRunMethod.evaluate(CitrusJUnit4Runner.java:217) [citrus-core-2.8.0.jar:?]
        at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.junit.runners.ParentRunner.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
        at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
        at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58) [junit-4.12.jar:4.12]
        at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
        at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365) [surefire-junit4-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:273) [surefire-junit4-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238) [surefire-junit4-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159) [surefire-junit4-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:384) [surefire-booter-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:345) [surefire-booter-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:126) [surefire-booter-2.22.2.jar:2.22.2]
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:418) [surefire-booter-2.22.2.jar:2.22.2]
Caused by: com.consol.citrus.exceptions.ValidationException: Failed to validate JSON text:
{"timestamp":"2020-02-06T14:00:46.436+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"} Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at com.consol.citrus.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:127) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:62) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.validation.AbstractMessageValidator.validateMessage(AbstractMessageValidator.java:46) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.ReceiveMessageAction.validateMessage(ReceiveMessageAction.java:231) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:128) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.dsl.actions.DelegatingTestAction.doExecute(DelegatingTestAction.java:54) ~[citrus-java-dsl-2.8.0.jar:?]
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.TestCase.executeAction(TestCase.java:220) ~[citrus-core-2.8.0.jar:?]
        ... 36 more
Caused by: java.lang.IllegalArgumentException: Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at org.springframework.util.Assert.isTrue(Assert.java:118) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]
        at com.consol.citrus.validation.json.JsonTextMessageValidator.validateJson(JsonTextMessageValidator.java:170) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:115) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.validation.json.JsonTextMessageValidator.validateMessage(JsonTextMessageValidator.java:62) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.validation.AbstractMessageValidator.validateMessage(AbstractMessageValidator.java:46) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.ReceiveMessageAction.validateMessage(ReceiveMessageAction.java:231) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.ReceiveMessageAction.doExecute(ReceiveMessageAction.java:128) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.dsl.actions.DelegatingTestAction.doExecute(DelegatingTestAction.java:54) ~[citrus-java-dsl-2.8.0.jar:?]
        at com.consol.citrus.actions.AbstractTestAction.execute(AbstractTestAction.java:42) ~[citrus-core-2.8.0.jar:?]
        at com.consol.citrus.TestCase.executeAction(TestCase.java:220) ~[citrus-core-2.8.0.jar:?]
        ... 36 more
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 13.907 s <<< FAILURE! - in edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT
[ERROR] testPlanMission(edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT)  Time elapsed: 9.88 s  <<< ERROR!
com.consol.citrus.exceptions.TestCaseFailedException:
Failed to validate JSON text:
{"timestamp":"2020-02-06T14:00:46.436+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"} Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT.testPlanMission(MissionPlannerIT.java:44)
Caused by: com.consol.citrus.exceptions.ValidationException:
Failed to validate JSON text:
{"timestamp":"2020-02-06T14:00:46.436+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"} Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT.testPlanMission(MissionPlannerIT.java:44)
Caused by: java.lang.IllegalArgumentException: Number of JSON entries not equal for element: '$.', expected '1' but was '5'
        at edu.mit.ll.mission_services.service.mission_planner.MissionPlannerIT.testPlanMission(MissionPlannerIT.java:44)

[INFO]
[INFO] Results:
[INFO]
[ERROR] Errors:
[ERROR]   MissionPlannerIT>JUnit4CitrusTest.run:70->JUnit4CitrusTest.invokeTestMethod:102 » TestCaseFailed
[INFO]
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.2:integration-test (integration-tests) @ mission-planner ---
[INFO] Skipping execution of surefire because it has already been run for this configuration
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.6.RELEASE:stop (post-integration-test) @ mission-planner ---
[INFO] Stopping application...
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.2:verify (default) @ mission-planner ---
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Mission Services - REST 0.0.1-SNAPSHOT:
[INFO]
[INFO] Mission Services - REST ............................ SUCCESS [  2.475 s]
[INFO] Common Utilities ................................... SUCCESS [  3.778 s]
[INFO] Mission Services Message Types ..................... SUCCESS [  1.823 s]
[INFO] Security ........................................... SUCCESS [  1.262 s]
[INFO] Mission Planner Client ............................. SUCCESS [  4.679 s]
[INFO] Mission Planner Service ............................ FAILURE [ 48.212 s]
[INFO] Route Generator Service ............................ SKIPPED
[INFO] Route Assessor Service ............................. SKIPPED
[INFO] UAV Service ........................................ SKIPPED
[INFO] Correlator Service ................................. SKIPPED
[INFO] Correlator Client .................................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:03 min
[INFO] Finished at: 2020-02-06T09:00:50-05:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-plugin:2.22.2:verify (default) on project mission-planner: There are test failures.
[ERROR]
[ERROR] Please refer to C:\Users\JO24447\workspace\REST_RST_Service\mission-services\mission-planner\target\failsafe-reports for the individual test results.
[ERROR] Please refer to dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :mission-planner

我认为测试失败报告它期待指定的 JSON 消息,但却收到了 503 消息 JSON。这让我很失望,让我认为问题在于任务规划器服务不可用。我认为这根本不是问题。

我defining/starting测试逻辑中的服务有什么问题吗?代理会妨碍吗?有什么方法可以衡量路线服务的健康状况(假设它们已经启动)?启动其他服务时是否缺少配置?

我很感激 Citrus Framework 有大量的文档和示例,它们非常有帮助。但是还有很多情况和使用场景没有讲到,让人不知如何是好。

更新:

还没有定论,但我可能偶然发现了一个解决方案。如果这真的能解决问题,一旦您弄明白了,它就会像大多数典型的解决方案一样:非常简单。

我正在浏览 github 上的柑橘样品,最后找到一个至少在某些方面与我的情况相似的例子。我的发现引起了我的注意,当我尝试时,似乎我终于解决了这个问题。

这是一个片段:

@Autowired
@Qualifier("networkBackendHttpServer")
private HttpServer networkHttpServer;

注意 @Autowired 注释。那就是我的代码中缺少的。记住我在上面有过思考。如果我早知道 @Qualifer 注释做了什么 而没有 做了什么。

解决方法很简单。我需要用 @Autowired.

注释我的 "server" 对象
public class MissionPlannerIT extends JUnit4CitrusTest {

  @Autowired
  @Qualifier("routeGeneratorServer")
  private HttpServer rgServer;
  @Autowired
  @Qualifier("routeAssessorServer")
  private HttpServer raServer;

我错误地假设 @Qualifier 注释也自动连接了这些对象。呵呵,没有。