Citrus框架-来自SUT的无法解释的HTTP 503

问题描述 投票:0回答:1

背景

我有一个简单的Spring Boot应用程序,其中包含三个服务。服务通过HTTP REST调用进行通信。以下是对服务的简要说明。

  • 任务计划器(localhost:9100

    • 安排任务的“计划”。调用路由生成器和路由评估器服务来完成工作。 “计划任务”动作由来自“客户端”的POST(/v1/missionServices/missionPlanning/planMission)触发。一个简单的响应消息返回给调用者。
  • 路由生成器(localhost:9110

    • 由任务计划者(/v1/missionServices/missionPlanning/generateRoute)调用时生成“路线”。向任务计划者返回响应消息。
  • 路由评估器(localhost:9120

    • 由任务计划者(/v1/missionServices/missionPlanning/assessRoute)调用时评估生成的“路线”。向任务计划者返回响应消息。

任务计划者“客户端”是通过向任务计划者发送POST请求来触发“计划任务”过程的第四项服务。这不是集成测试的一部分。相反,使用Citrus测试。

目标

我正在尝试使用Citrus框架对服务进行单独或整体(端到端)的集成测试。对于较简单的服务案例(即路线生成器和路线评估器),我已经取得了成功,但事实证明,测试任务计划程序存在许多困难。

下面是我为任务计划者编写的Citrus测试。目前,我正在“模拟”路由生成器和路由评估器服务,但是对于端到端测试,将需要弄清楚如何做到这三个服务都将“生效”-我现在不必担心。我基于发现的示例以及从我的经验中学到的知识来构建它。

MissionPlannerIT.java:

public class MissionPlannerIT extends JUnit4CitrusTest {

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

  @Autowired
  @Qualifier("missionPlannerClient")
  private HttpClient sutClient;

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

    // Call mission planner to plan a mission.
    runner.http(builder -> builder
        .client(sutClient)
        .send()
        .post("/v1/missionServices/missionPlanning/planMission"));
    runner.echo("Sent plan mission");

    // Set route generator to receive and validate generate route command.
    runner.http(builder -> builder
        .server(rgServer)
        .receive()
        .post("/v1/missionServices/missionPlanning/generateRoute")
        .accept(ContentType.APPLICATION_JSON.getMimeType())
        .payload(new ClassPathResource("templates/gen-route-command.json")));
    runner.echo("RG received generate route");

    // Set route generator to return response.
    runner.http(builder -> builder
        .server(rgServer)
        .send()
        .response(HttpStatus.OK)
        .messageType(MessageType.JSON)
        .contentType(ContentType.APPLICATION_JSON.getMimeType())
        .payload(new ClassPathResource("templates/gen-route-status.json")));
    runner.echo("RG sent generate route status");

    // Set route assessor to receive and validate assess route command.
    runner.http(builder -> builder
        .server(raServer)
        .receive()
        .post("/v1/missionServices/missionPlanning/assessRoute")
        .accept(ContentType.APPLICATION_JSON.getMimeType())
        .payload(new ClassPathResource("templates/assess-route-command.json")));
    runner.echo("RA received assess route");

    // Set route assessor to return response.
    runner.http(builder -> builder
        .server(raServer)
        .send()
        .response(HttpStatus.OK)
        .messageType(MessageType.JSON)
        .contentType(ContentType.APPLICATION_JSON.getMimeType())
        .payload(new ClassPathResource("templates/assess-route-status.json")));
    runner.echo("RA sent assess route status");

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

    // Shut down route services. TODO may not need this
    runner.stop(rgServer);
    runner.stop(raServer);
  }
  // @formatter:on

}

EndpointConfig.java:

@Configuration
public class EndpointConfig {

  @Bean
  public HttpClient missionPlannerClient() {
    return CitrusEndpoints.http().client().requestUrl("http://localhost:9100").build();
  }

  @Bean
  public Server routeGeneratorServer() {
    return CitrusEndpoints.http().server().port(9110).timeout(10000).autoStart(true).build();
  }

  @Bean
  public Server routeAssessorServer() {
    return CitrusEndpoints.http().server().port(9120).timeout(10000).autoStart(true).build();
  }

  @Bean("defaultJsonMessageValidator")
  public JsonTextMessageValidator jsonValidator() {
    return new JsonTextMessageValidator();
  }

}

我有两种方法运行此测试:1)作为Maven构建的一部分,以及2)使用eclipse。将其作为Maven构建运行时遇到问题,其中大多数测试控制台的输出均未输出(请参阅Citrus Framework logging - how to enable/useCitrus Framework - echo action does not "echo")。当我通过Eclipse运行它时,我需要在运行测试之前手动启动任务计划程序。

输出

我包括了Eclipse运行方法中的部分控制台日志,因为它包含使用maven方法时丢失的信息。我将尝试包括我认为相关的部分,并一路包括我的笔记/想法。

摘要:

  • 测试步骤1:发送-向任务计划者进行初始POST以开始流程
  • 测试步骤3:接收-将模拟路线生成器设置为从任务计划者接收POST请求以生成路线
  • 测试步骤5:发送-设置模拟路由生成器以返回响应消息
  • 测试步骤7:接收-将模拟路线评估器设置为从任务计划者接收POST请求以评估路线
  • 测试步骤9:发送-设置模拟路线评估器以返回响应消息
  • 测试步骤11:接收-希望收到任务计划者的响应消息

测试步骤1-向任务计划者执行初始POST以启动过程:

15:00:50.689 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 1: send
15:00:52.598 [main] DEBUG com.consol.citrus.message.correlation.DefaultCorrelationManager - Saving correlation key for 'citrus_message_correlator_missionPlannerClient'
15:00:52.598 [main] DEBUG com.consol.citrus.context.TestContext - Setting variable: citrus_message_correlator_missionPlannerClient with value: 'citrus_message_id = '3f242515-7eb2-4aed-a85c-53a4560029b4''
15:00:52.598 [main] DEBUG com.consol.citrus.http.client.HttpClient - Sending HTTP message to: 'http://localhost:9100/v1/missionServices/missionPlanning/planMission'
15:00:52.598 [main] DEBUG com.consol.citrus.http.client.HttpClient - Message to send:

15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - outboundHeaderNames=[Accept, Accept-Charset, Accept-Encoding, Accept-Language, Accept-Ranges, Authorization, Cache-Control, Connection, Content-Length, Content-Type, Cookie, Date, Expect, From, Host, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Max-Forwards, Pragma, Proxy-Authorization, Range, Referer, TE, Upgrade, User-Agent, Via, Warning]
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_message_timestamp] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_message_type] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_request_path] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_http_request_uri] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[id] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_message_id] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[citrus_http_method] WILL NOT be mapped
15:00:52.601 [main] DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper - headerName=[timestamp] WILL NOT be mapped
15:00:52.607 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP POST http://localhost:9100/v1/missionServices/missionPlanning/planMission
15:00:52.610 [main] DEBUG org.springframework.web.client.RestTemplate - Accept=[text/plain, application/json, application/*+json, */*]
15:00:52.611 [main] DEBUG org.springframework.web.client.RestTemplate - Writing [] as "text/plain;charset=UTF-8"
15:00:52.656 [main] DEBUG com.consol.citrus.http.interceptor.LoggingClientInterceptor - Sending Http request message
15:00:52.657 [main] DEBUG Logger.Message_OUT - POST http://localhost:9100/v1/missionServices/missionPlanning/planMission
Accept:text/plain, application/json, application/*+json, */*
Content-Type:text/plain;charset=UTF-8
Content-Length:0
Accept-Charset:big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1166, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp

我认为这是记录活动,表明任务计划者已向路线生成器发出POST请求:

15:00:52.801 [qtp923083575-34] DEBUG org.eclipse.jetty.server.HttpChannel - REQUEST for //localhost:9110/v1/missionServices/missionPlanning/generateRoute on HttpChannelOverHttp@4df838fc{r=1,c=false,c=false/false,a=IDLE,uri=//localhost:9110/v1/missionServices/missionPlanning/generateRoute,age=1}
POST //localhost:9110/v1/missionServices/missionPlanning/generateRoute HTTP/1.1
Accept: application/json
Content-Type: application/json
elastic-apm-traceparent: 00-eb0d1dffcf09adda45d39323efc6f883-7236b8b42e4e90d5-01
Content-Length: 311
Host: localhost:9110
Connection: keep-alive
User-Agent: Apache-HttpClient/4.5.9 (Java/1.8.0_201)
Accept-Encoding: gzip,deflate

...
15:00:52.828 [qtp923083575-34] DEBUG com.consol.citrus.http.interceptor.LoggingHandlerInterceptor - Received Http request:
HTTP/1.1 POST /v1/missionServices/missionPlanning/generateRoute
elastic-apm-traceparent:00-eb0d1dffcf09adda45d39323efc6f883-7236b8b42e4e90d5-01
Accept:application/json
Connection:keep-alive
User-Agent:Apache-HttpClient/4.5.9 (Java/1.8.0_201)
Host:localhost:9110
Accept-Encoding:gzip,deflate
Content-Length:311
Content-Type:application/json
{"header":{"timestamp":1581364852723,"typeID":"edu.mit.ll.mission_services.messages.GenerateRouteCommand","transaction":{"id":2,"startTime":1581364852723},"signature":{"algorithm":null,"keySize":0,"keyValue":null,"sender":null}},"commandID":"60b684f1-5065-47d6-8e7d-a4f101b44d22","commandType":"GENERATE_ROUTE"}
...
15:00:52.851 [qtp923083575-34] DEBUG com.consol.citrus.channel.ChannelSyncProducer - Sending message to channel: 'routeGeneratorServer.inbound'
15:00:52.851 [qtp923083575-34] DEBUG com.consol.citrus.channel.ChannelSyncProducer - Message to send is:
HTTPMESSAGE [id: 900d8f51-b1cf-427e-9f00-cd5b242b5dca, payload: {"header":{"timestamp":1581364852723,"typeID":"edu.mit.ll.mission_services.messages.GenerateRouteCommand","transaction":{"id":2,"startTime":1581364852723},"signature":{"algorithm":null,"keySize":0,"keyValue":null,"sender":null}},"commandID":"60b684f1-5065-47d6-8e7d-a4f101b44d22","commandType":"GENERATE_ROUTE"}][headers: {Accept=application/json, Connection=keep-alive, User-Agent=Apache-HttpClient/4.5.9 (Java/1.8.0_201), Host=localhost:9110, Accept-Encoding=gzip,deflate, Content-Length=311, contentType=application/json;charset=UTF-8, citrus_message_id=900d8f51-b1cf-427e-9f00-cd5b242b5dca, citrus_message_timestamp=1581364852849, elastic-apm-traceparent=00-eb0d1dffcf09adda45d39323efc6f883-7236b8b42e4e90d5-01, Content-Type=application/json;charset=UTF-8, citrus_http_request_uri=/v1/missionServices/missionPlanning/generateRoute, citrus_request_path=/v1/missionServices/missionPlanning/generateRoute, citrus_endpoint_uri=/v1/missionServices/missionPlanning/generateRoute, citrus_http_context_path=, citrus_http_query_params=, citrus_query_params=, citrus_http_version=HTTP/1.1, citrus_http_method=POST}]
15:00:52.851 [qtp923083575-34] INFO com.consol.citrus.channel.ChannelSyncProducer - Message was sent to channel: 'routeGeneratorServer.inbound'
15:00:57.729 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 503 Service Unavailable[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Date: Mon, 10 Feb 2020 20:00:52 GMT[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Content-Type-Options: nosniff[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-XSS-Protection: 1; mode=block[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Pragma: no-cache[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Frame-Options: DENY[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Content-Type-Options: nosniff[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Content-Type: application/json;charset=utf-8[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Transfer-Encoding: chunked[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "B0[\r][\n]"
15:00:57.730 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "{"timestamp":"2020-02-10T20:00:57.728+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"}"
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << HTTP/1.1 503 Service Unavailable
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Date: Mon, 10 Feb 2020 20:00:52 GMT
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Content-Type-Options: nosniff
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-XSS-Protection: 1; mode=block
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Pragma: no-cache
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Frame-Options: DENY
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Content-Type-Options: nosniff
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Content-Type: application/json;charset=utf-8
15:00:57.736 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Transfer-Encoding: chunked
15:00:57.747 [main] DEBUG org.apache.http.impl.execchain.MainClientExec - Connection can be kept alive indefinitely
15:00:57.751 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
15:00:57.751 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "0[\r][\n]"
15:00:57.751 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"

我们对问题的第一个迹象-顺便说一下,我们仍在测试步骤1:

15:00:57.752 [main] DEBUG com.consol.citrus.http.interceptor.LoggingClientInterceptor - Received Http response message
15:00:57.752 [main] DEBUG Logger.Message_IN - HTTP/1.1 503 SERVICE_UNAVAILABLE Service Unavailable
Date:Mon, 10 Feb 2020 20:00:52 GMT
X-Content-Type-Options:nosniff,nosniff
X-XSS-Protection:1; mode=block
Pragma:no-cache
X-Frame-Options:DENY
Content-Type:application/json;charset=utf-8
Transfer-Encoding:chunked

{"timestamp":"2020-02-10T20:00:57.728+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"}
15:00:57.752 [main] DEBUG org.springframework.web.client.RestTemplate - Response 503 SERVICE_UNAVAILABLE
15:00:57.757 [main] INFO com.consol.citrus.http.client.HttpClient - Caught HTTP rest client exception: 503 Service Unavailable
15:00:57.757 [main] INFO com.consol.citrus.http.client.HttpClient - Propagating HTTP rest client exception according to error handling strategy

测试步骤1的完成:

15:00:57.760 [main] DEBUG com.consol.citrus.message.correlation.DefaultCorrelationManager - Saving correlated object for 'citrus_message_id = '3f242515-7eb2-4aed-a85c-53a4560029b4''
15:00:57.760 [main] INFO com.consol.citrus.report.LoggingReporter - 
15:00:57.760 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 1 SUCCESS

测试步骤3-模拟路线生成器收到任务计划者的请求:

15:00:57.779 [main] DEBUG com.consol.citrus.util.FileUtils - Reading file resource: 'gen-route-command.json' (encoding is 'UTF-8')
15:00:57.781 [main] INFO com.consol.citrus.report.LoggingReporter - 
15:00:57.781 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 3: receive
15:00:57.791 [main] DEBUG com.consol.citrus.channel.ChannelConsumer - Receiving message from: routeGeneratorServer.inbound
15:00:57.792 [main] DEBUG com.consol.citrus.channel.ChannelConsumer - Received message from: routeGeneratorServer.inbound
... Received request from mission planner
15:00:57.801 [main] DEBUG com.consol.citrus.validation.MessageValidatorRegistry - Found 4 message validators for message type: XML
15:00:57.801 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Start JSON message validation ...
15:00:57.801 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Received message:
HTTPMESSAGE [id: 900d8f51-b1cf-427e-9f00-cd5b242b5dca, payload: {"header":{"timestamp":1581364852723,"typeID":"edu.mit.ll.mission_services.messages.GenerateRouteCommand","transaction":{"id":2,"startTime":1581364852723},"signature":{"algorithm":null,"keySize":0,"keyValue":null,"sender":null}},"commandID":"60b684f1-5065-47d6-8e7d-a4f101b44d22","commandType":"GENERATE_ROUTE"}][headers: {Accept=application/json, Connection=keep-alive, User-Agent=Apache-HttpClient/4.5.9 (Java/1.8.0_201), Host=localhost:9110, Accept-Encoding=gzip,deflate, Content-Length=311, contentType=application/json;charset=UTF-8, citrus_message_id=900d8f51-b1cf-427e-9f00-cd5b242b5dca, citrus_message_timestamp=1581364852849, elastic-apm-traceparent=00-eb0d1dffcf09adda45d39323efc6f883-7236b8b42e4e90d5-01, Content-Type=application/json;charset=UTF-8, citrus_http_request_uri=/v1/missionServices/missionPlanning/generateRoute, citrus_request_path=/v1/missionServices/missionPlanning/generateRoute, citrus_endpoint_uri=/v1/missionServices/missionPlanning/generateRoute, citrus_http_context_path=, citrus_http_query_params=, citrus_query_params=, citrus_http_version=HTTP/1.1, citrus_http_method=POST, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3db663d0, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@3db663d0, id=10be4cec-6d61-d00a-f0e6-baed32421725, timestamp=1581364852856}]
15:00:57.802 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Control message:
HTTPMESSAGE [id: d0d27c94-533e-4724-b87a-5a8d4d05950d, payload: {
    "header": {
        "timestamp": "@isNumber()@",
        "typeID": "edu.mit.ll.mission_services.messages.GenerateRouteCommand",
        "transaction": {
            "id": "@isNumber()@",
            "startTime": "@isNumber()@"
        },
        "signature": {
            "algorithm": null,
            "keySize": 0,
            "keyValue": null,
            "sender": null
        }
    },
    "commandID": "@ignore@",
    "commandType": "GENERATE_ROUTE"
}][headers: {citrus_message_id=d0d27c94-533e-4724-b87a-5a8d4d05950d, citrus_message_timestamp=1581364857769, citrus_http_method=POST, citrus_http_request_uri=/v1/missionServices/missionPlanning/generateRoute, citrus_request_path=/v1/missionServices/missionPlanning/generateRoute, Accept=application/json, citrus_message_type=XML}]

15:00:57.923 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 3 SUCCESS

跳到步骤10的完成(回显)。我认为这是第9步的活动完成。

15:00:57.986 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 10 SUCCESS
15:00:57.987 [qtp203936099-36] DEBUG org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor - Found 'Content-Type:application/json' in response
15:00:57.987 [qtp203936099-36] DEBUG org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor - Writing ["{
    "header": {
        "timestamp": 1580761681867,
        "typeID": "edu.mit.ll.mission_services.messages.Asse (truncated)...]
15:00:57.987 [qtp203936099-36] DEBUG com.consol.citrus.http.interceptor.LoggingHandlerInterceptor - Sending Http response:
com.consol.citrus.http.servlet.GzipHttpServletResponseWrapper@61196037
{
    "header": {
        "timestamp": 1580761681867,
        "typeID": "edu.mit.ll.mission_services.messages.AssessRouteStatus",
        "transaction": {
            "id": 1,
            "startTime": 1580761681867
        },
        "signature": {
            "algorithm": null,
            "keySize": 0,
            "keyValue": null,
            "sender": null
        }
    },
    "commandID": "0710d523-43da-4f68-90c7-a2b4544a955d",
    "status": "COMPLETED"
}
15:00:57.987 [qtp203936099-36] DEBUG com.consol.citrus.http.servlet.CitrusDispatcherServlet - Completed 200 OK

最后,测试报告失败,尽管我认为问题始于步骤1。

15:00:57.998 [main] DEBUG com.consol.citrus.report.LoggingReporter - TEST STEP 11: receive
15:00:58.000 [main] DEBUG com.consol.citrus.validation.MessageValidatorRegistry - Found 4 message validators for message type: JSON
15:00:58.000 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Start JSON message validation ...
15:00:58.000 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Received message:
HTTPMESSAGE [id: 43da4bd7-9929-4536-a9e6-caaabcb72c62, payload: {"timestamp":"2020-02-10T20:00:57.728+0000","status":503,"error":"Service Unavailable","message":"Service Unavailable","path":"/v1/missionServices/missionPlanning/planMission"}][headers: {Transfer-Encoding=chunked, Pragma=no-cache, contentType=application/json;charset=utf-8, Date=1581364852000, citrus_message_id=43da4bd7-9929-4536-a9e6-caaabcb72c62, citrus_message_timestamp=1581364857760, X-Frame-Options=DENY, X-Content-Type-Options=nosniff,nosniff, X-XSS-Protection=1; mode=block, Content-Type=application/json;charset=utf-8, citrus_http_status_code=503, citrus_http_reason_phrase=SERVICE_UNAVAILABLE, citrus_http_version=HTTP/1.1}]
15:00:58.000 [main] DEBUG com.consol.citrus.validation.json.JsonTextMessageValidator - Control message:
HTTPMESSAGE [id: 069509f7-2591-452f-886a-f3c1bb556b09, payload: {
  "message": "Transaction complete"
}][headers: {citrus_message_id=069509f7-2591-452f-886a-f3c1bb556b09, citrus_message_timestamp=1581364857989, citrus_http_status_code=200, citrus_http_reason_phrase=OK, citrus_message_type=JSON}]
15:00:58.002 [main] INFO com.consol.citrus.report.LoggingReporter - 
15:00:58.004 [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-10T20:00:57.728+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'

想法

SUT(任务计划程序服务)与模拟生成器之间的交互似乎都按预期工作。消息来回传递,似乎没有问题。我不明白的是HTTP 503错误的外观。它似乎在第一步测试中发生,但我不知道可能是什么错误。

我什至不知道如何尝试调试任何一个。我对HTTP的工作方式并不熟悉。从我的角度来看,很多正在发生的事情在幕后发生,我不知道该怎么看那里发生的事情。

[如果有人在我所做的事情中发现错误,请告诉我。如果有人有什么想法可能会发生什么,那将非常有帮助。最后,非常感谢您提出有关尝试调试的建议。

UPDATE

我修改了测试,将超时调用添加到客户端和服务器端点。例如:

  @Bean
  public HttpClient missionPlannerClient() {
    return CitrusEndpoints.http().client().requestUrl("http://localhost:9100").timeout(30000).build();
  }

不幸的是,这对我的问题没有影响。

我还已将以下内容添加到SUT(任务计划程序)application.yml:

server:
  port: 9100
  ...
  jetty:
    http:
      idleTimeout: 60000
      stopTimeout: 60000
      connection-idle-timeout: 60000
      thread-idle-timeout: 60000

这似乎也没有影响。我不确定100%是否使用了正确的属性。

NOTE

我进行了一个有趣的实验,该实验不涉及Citrus,但是我在其中运行了所有三个真实服务,然后尝试通过Postman进行“计划任务”调用。我得到了相同的HTTP 503响应。

现在事实证明,真正的“路由”服务具有内置的可配置延迟,可以模拟长时间运行的任务。每个服务的延迟设置为5秒。

我将这些延迟设置为0,然后再次与Postman一起发布。这次成功了!我假设Postman具有默认超时,并且服务延迟超过了该时间,从而导致观察到的结果。也许?我想我会收到某种超时消息,而不是“服务不可用”。

延迟肯定会对该测试结果产生影响,但是,在Citrus测试案例中,“路由”服务正在被嘲笑,不应引入任何人为延迟。

只是一个有趣的观察。

java spring-boot spring-rest citrus-framework
1个回答
0
投票

[您在Http客户端发送初始请求的第一个测试步骤中缺少fork=true。 Http本质上是一种同步协议,这意味着测试的第一步将等待Http响应,然后再继续其他测试步骤。这意味着未执行所有其他测试步骤,因此您的Http服务器模拟将无法正常运行。

我猜您因此会在客户端和Http服务器端都遇到很多请求超时。这可能会导致Http 503。

© www.soinside.com 2019 - 2024. All rights reserved.