Citrus httpServer & httpClient tests

229 Views Asked by At

I'm using Citrus for perform integration tests based on http requests. The test should perform steps as follows:

  1. Sending a POST http request to external service with a callback url as body attribute ex: {... "callback": "http://url-to-be-called" ...}
  2. Waiting for 3 sequential http requests from the external service

I've used Citrus httpClient to send the Post Request, and Citrus httpServer to exspose endpoints that the service will call using the callback url. So,

  • httpClient --> sends POST to ext service
  • <-- ext service responds OK
  • (after several minutes)
  • <-- ext service invokes httpServer API
  • httpClient --> responds OK
  • (after several minutes)
  • <-- ext service invokes httpServer API
  • httpClient --> responds OK
  • (after several minutes)
  • <-- ext service invokes httpServer API
  • httpClient --> responds OK

My test code is

parallel().actions(
        sequential().actions(
                // wait for callback
                http(httpActionBuilder -> httpActionBuilder
                        .server(httpServer)
                        .receive()
                        .post("/api/callback")
                        .contentType("application/json;charset=UTF-8")
                        .accept("text/plain,application/json,application/*+json,*/*")
                ),
                // callback response
                http(httpActionBuilder -> httpActionBuilder
                        .server(httpServer)
                        .send()
                        .response(HttpStatus.OK)
                        .contentType("application/json")
                )),
                sequential().actions(
                        
                        http(httpActionBuilder -> httpActionBuilder
                                .client(httpClient)
                                .send()
                                .post("/externalapi)
                                .payload("{" +
                                        "\"ret\": \"OK\"" +
                                        "}")
                                .messageType(MessageType.JSON)
                                .contentType(ContentType.APPLICATION_JSON.getMimeType())
                        ),
                        
                        http(httpActionBuilder -> httpActionBuilder
                                .client(httpClient)
                                .receive()
                                .response(HttpStatus.OK)
                                .messageType(MessageType.JSON)
                                        .payload("{" +
                                                "\"ret\": \"OK\"" +
                                                "}")
                        )
                )
        );

My configurations

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

@Bean
public HttpServer httpServer() throws Exception {
    return CitrusEndpoints.http()
            .server()
            .port(8080)
            .endpointAdapter(dispatchingEndpointAdapter())
            .timeout(300000)
            .autoStart(true)
            .build();
}

@Bean
public RequestDispatchingEndpointAdapter dispatchingEndpointAdapter() {
    RequestDispatchingEndpointAdapter dispatchingEndpointAdapter = new RequestDispatchingEndpointAdapter();
    dispatchingEndpointAdapter.setMappingKeyExtractor(mappingKeyExtractor());
    dispatchingEndpointAdapter.setMappingStrategy(mappingStrategy());
    return dispatchingEndpointAdapter;
}

@Bean
public HeaderMappingKeyExtractor mappingKeyExtractor() {
    HeaderMappingKeyExtractor mappingKeyExtractor = new HeaderMappingKeyExtractor();
    mappingKeyExtractor.setHeaderName(HttpMessageHeaders.HTTP_REQUEST_URI);
    return mappingKeyExtractor;
}

@Bean
public SimpleMappingStrategy mappingStrategy() {
    SimpleMappingStrategy mappingStrategy = new SimpleMappingStrategy();

    Map<String, EndpointAdapter> mappings = new HashMap<>();

    mappings.put("/api/callback", callbackResponseAdapter());

    mappingStrategy.setAdapterMappings(mappings);
    return mappingStrategy;
}

@Bean
public EndpointAdapter callbackResponseAdapter() {
    StaticResponseEndpointAdapter endpointAdapter = new StaticResponseEndpointAdapter();
    endpointAdapter.setMessagePayload("{" +
            "\"ret\": \"OK\"," +
            "}");
    return endpointAdapter;
}

The httpClient steps works fine, but when I add the HttpServer I get this error

com.consol.citrus.exceptions.TestCaseFailedException: Unable to create endpoint for static endpoint adapter type 'class com.consol.citrus.endpoint.adapter.RequestDispatchingEndpointAdapter'
1

There are 1 best solutions below

0
On BEST ANSWER

In your http-server configuration you are using both static request dispatcher and test action based dynamic response generation. This is not valid.

Please choose only one approach at a time. Either remove the request dispatcher configuration completely or do not try to receive the incoming requests in your test via receive/send action.

By the way the parallel-sequential blocks you are using may not be required. You can use fork=true option on the 1st client request instead and sequentially wait for the Http requests to arrive. This should simplify the test a lot.