Search code examples
javajsoncucumberspring-test

Spring Boot + Cucumber test: cucumber cannot detect my step definition method due to double quotation escaping in JSON


In a Spring Boot REST application, I want to check with Cucumber-jvm that the returned JSON is exactly what I expect. However, because I have to use double quotation around JSON key names, Cucumber cannot detect the correct step definition method and thus the test cannot pass.

Here is the expected JSON result:

{"fields":[],"errorMsg":"BIN not found"}

Cucumber step definition:

Given bin number is <bin>
When binlookup searches with this bin number
Then binlookup returns <result> and status code <code>

Examples: 
  | bin      | result                                                       | code |
  | "222222" | "{\"fields\":[\"bin\"]\,\"errorMsg\":\"Invalid Argument\"}"   | 404  |

The corresponding method:

@Then("^binlookup returns \"([^\"]*)\" and status code \\d$")
public void binlookup_returns_and_status_code(String result, Integer code) throws Exception {
    assertThat(this.results.getResponse().getContentType()).isEqualTo(MediaType.APPLICATION_JSON_UTF8_VALUE);
    assertThat(this.results.getResponse().getStatus()).isEqualTo(code);
    assertThat(this.results.getResponse().getContentAsString().length()).isNotEqualTo(0);
    assertThat(this.results.getResponse().getContentAsString()).isEqualTo(result);
}

When running the test, I do have correct returned JSON:

{"fields":["bin"],"errorMsg":"Invalid Argument"}

But I see test errors and Cucumber cannot detect my method, and gives me tips like:

You can implement missing steps with the snippets below:

@Then("binlookup returns {string}\\:[],\\{string}\\:\\{string} and status code {int}")
public void binlookup_returns_and_status_code(String string, String string2, String string3, Integer int1) {
    // Write code here that turns the phrase above into concrete actions
    throw new PendingException();
}

Obviously, it pairs the first " with the first escaped " and sees {\"fields as the first parameter, but it is wrong.

But, I cannot quote the JSON string with ' ' because it will not be the case.

What can I do?


If it is impossible, how can I verify the JSON has the data I expect?


Solution

  • I read today somewhere that from now on, regex will be deprecated(reason unknown), and they are moving to Cucumber expression. I am with Cucumber 3.0.2, where Cucumber expression is available. So I tried that and suddenly, all is fine now.

    I also noted that I have some error in the OP, and I corrected them too.

    I also find that you can use single quotation mark around the whole string, so if you have many double quotations to escape, you should surround the whole string with single quotation and you can avoid escaping the double quotation then.

    Now I have:

    Examples: 
      | bin      | result                                                       | code |
      | "222222" | '{"fields":[],"errorMsg":"BIN not found"}'                   | 404  |
    

    And method annotated like:

    @Then("binlookup returns {string} and status code {int}")
    public void binlookup_returns_and_status_code(String result, Integer code) throws Exception {
        ...
    

    (Note that regex cannot coexist with cucumber expression; ^ and $ and other things will cause parsing error in cucumber expression)

    And I can pass all the tests. At least in Eclipse. In IntelliJ I don't know.

    ...
    Then binlookup returns '{"fields":[],"errorMsg":"BIN not found"}' and status code 404 # BinInfoControllerCucumberTests.binlookup_returns_and_status_code(String,Integer)
    

    You can see that the method is found. Before was null(cannot be found).

    Single quotation + regex expression does not work.

    Remember: in the string, just escape the symbol which you use to surround the whole string, which can be single or double quotation.