Citrus Framework - Can a variable be assigned from

2019-07-29 05:01发布

问题:

I'm trying to test the following two REST calls:

Request 1

GET getLatestVersion
Response: {"version": 10}

Request 2

POST getVersionData (body={"version": 10})
Response: {"version": 10, data: [...]}

Is it possible to assign the "version" from Request 1 to a variable to use in Request 2 within the same test?

@CitrusTest(name = "SimpleIT.getVersionTest")
public void getVersionTest() { 
    // Request 1
    http()
            .client("restClient")
            .send()
            .get("/getLatestVersion")
            .accept("application/json");

    http()
            .client("restClient")
            .receive()
            .response(HttpStatus.OK)
            .messageType(MessageType.JSON)
            // Can the version be assigned to a variable here?
            .payload("{\"version\":10}");

    // Request 2
    http()
            .client("restClient")
            .send()
            .post("/getVersionData")
            // Idealy this would be a Citrus variable from the previous response
            .payload("{\"version\":10}")
            .accept("application/json");

    http()
            .client("restClient")
            .receive()
            .response(HttpStatus.OK)
            .messageType(MessageType.JSON)
            .payload("\"version\": 10, data: [...]");
}

回答1:

You can use JsonPath expressions:

http()
    .client("restClient")
    .receive()
    .response(HttpStatus.OK)
    .messageType(MessageType.JSON)
    .extractFromPayload("$.version", "apiVersion")
    .payload("{\"version\":\"@ignore@\"}");

Or you can use the create variable matcher in payload:

http()
    .client("restClient")
    .receive()
    .response(HttpStatus.OK)
    .messageType(MessageType.JSON)
    .payload("{\"version\":\"@variable('apiVersion')@\"}");

Both options will create a new test variable apiVersion that you can reference with ${apiVersion} in further test actions.



回答2:

One approach that works is to extract the value from the TestContext and assign it as a variable

@CitrusTest(name = "SimpleIT.getVersionTest")
@Test
public void getVersionTest(@CitrusResource TestContext context) {

    http(httpActionBuilder -> httpActionBuilder
        .client("restClient")
        .send()
        .get("/getLatestVersion")
        .name("request1")
        .accept("application/json")
    );

    http(httpActionBuilder -> httpActionBuilder
        .client("restClient")
        .receive()
        .response(HttpStatus.OK)
        .messageType(MessageType.JSON)
        .payload("{\"version\":\"@greaterThan(0)@\"}")
    );

    // This extracts the version and assigns it as a variable
    groovy(action -> action.script(new ClassPathResource("addVariable.groovy")));

    http(httpActionBuilder -> httpActionBuilder
            .client("restClient")
            .send()
            .post("/getVersionData")
            .payload("{\"version\":${versionId}}")
            .accept("application/json")
    );

    http(httpActionBuilder -> httpActionBuilder
            .client("restClient")
            .receive()
            .response(HttpStatus.OK)
            .messageType(MessageType.JSON)
    );
}

addVariable.groovy

This extracts the variable from the response and adds it to the TestContext.

import com.consol.citrus.message.Message
import groovy.json.JsonSlurper

Message message = context.getMessageStore().getMessage("receive(restClient)");

def jsonSlurper = new JsonSlurper();
def payload = jsonSlurper.parseText((String) message.getPayload())

// Set the version as a variable in the TestContext
context.getVariables().put("versionId", payload.version)

Questions

  • Is there a neater way to do this?
  • Is there a way to name the messages within the MessageStore?