简体   繁体   中英

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?

The cucumber's stepdefs is all about regex. The arguments are captured using capture groups, you only need to use a regex that match the json.

I think it would work to you:

@Then("^binlookup returns \"(.*)\" and status code \\d$")

The \\"(.*)\\" regex will capture everything inside double quotes.

The entire regex is: "binlookup returns " , followed by everything inside double quotes (the \\"(.*)\\" regex), followed by " and status code " , followed by a number (the \\d regex).

And in the stepDef file:

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

Note that you don't need to escape the double quotes inside json using this approach.

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.

use the @DocStringType cucumber expression introduced in Cucumber-JVM 5 ( https://github.com/cucumber/cucumber-jvm/blob/main/release-notes/v5.0.0.md ) instead of using regular expressions

You can find an example here https://blog.executeautomation.com/all-new-cucumber-jvm-5-with-its-cucumber-expression

在此处输入图片说明

If a single quote (') is used at the step level and if the step is defined with {string} place holder this can be achieved. I was on cucumber version 6.10.3 . Pretty sure this will work on some previous versions(maybe version 4.0.0+) too.

Create a stepdefintion like:

@Then("binlookup returns {string} and status code {int}")
public void binlookupReturnsAndStatusCode(String result, Integer code) throws Exception {
    System.out.println(result);
    System.out.println(code);
}

And scenario like below where the json string doesn't have to be escaped:

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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM