如何在 Scenario 对象中为 属性 设置默认值(未调用构造函数!)
How to set default value for property in a Scenario object (constructor not called!)
考虑以下几点:
@Given("^this stuff:$")
public void this_stuff(List<ScenarioStuff> stuffList) throws Throwable {
stuffList.get(0).isHappy();
}
和特征:
Given this stuff:
|Name|
|Miguel|
最后,场景对象:
ScenarioStuff{
private String name;
private boolean happy;
(getters and setters for name and happy, inlcuding:)
public boolean isHappy(){
return happy;
}
这是我的发现:
- stuffList.get(0).isHappy();是假的;
- 即使
private boolean happy=true;
它仍然是错误的
ScenarioStuff(){ happy=true)
的默认构造函数仍然为 false
- 代码不会在该构造函数中使用断点中断。
问题:
如果未在功能 table 中作为参数提供,我如何默认 happy=true
?
Cucumber 使用 XStream to convert step definition arguments to Java objects, so to answer this we have to dig in XStream 的方法来做到这一点。
如 this answer to an XStream question 所述,一种选择是使用 readResolve 方法(如果可用,XStream 显然会使用它来设置对象。
在我的特殊情况下,将 happy 变量从 boolean
更改为 Boolean
后,我最终得到了如下实现:
ScenarioStuff{
private String Name;
private Boolean happy;
private Object readResolve() {
if(happy == null){
happy = true;
}
return this;
}
}
我还读到可以为 marshal/unmarshal 对象实现一个转换器,但我没有探索这个选项,因为 1) 它看起来不那么简单,并且 2) 我没有立即看到一个人会怎么做在黄瓜设置中注册这个新转换器。
更新
我添加了布尔值并让它们也起作用。
Scenario: An international coffee shop must handle currencies
Given the price list for an international coffee shop
| product | currency | price | happy |
| coffee | EUR | 1 | true |
| donut | SEK | 18 | false |
When I buy "1" "coffee" and "1" "donut"
Then I should pay "1" EUR be "happy" and "18" SEK be "unhappy"
步骤定义文件
public class datatable_steps {
private HashMap<String, Price> intPriceList = new HashMap<String, Price>();
private int sekSum;
private int euroSum;
@Given("^the price list for an international coffee shop$")
public void the_price_list_for_an_international_coffee_shop(List<Price> prices) {
int numPrices = prices.size();
System.out.println("numPrices = " + numPrices);
for(Price price : prices) {
String key = price.getProduct();
intPriceList.put(key, price);
}
}
@When("^I buy \"(\d+)\" \"(.*)\" and \"(\d+)\" \"(.*)\"$")
public void i_order_coffee_and_donut(int numberOfFirstItems, String firstItem,
int numberOfSecondItems, String secondItem) throws Throwable {
Price firstPrice = intPriceList.get(firstItem);
calculate(numberOfFirstItems, firstPrice);
Price secondPrice = intPriceList.get(secondItem);
calculate(numberOfSecondItems, secondPrice);
}
private void calculate(int numberOfItems, Price price) {
if (price.getCurrency().equals("SEK")) {
sekSum += numberOfItems * price.getPrice();
return;
}
if (price.getCurrency().equals("EUR")) {
euroSum += numberOfItems * price.getPrice();
return;
}
throw new IllegalArgumentException("The currency is unknown");
}
@Then("^I should pay \"(\d+)\" EUR be \"(.*)\" and \"(\d+)\" SEK be \"(.*)\"$")
public void should_I_pay_EUR_and_SEK(int expectedEuroSum, String eurHappy, int expectedSekSum, String sekHappy) throws Throwable {
boolean eurHappyBool = false;
boolean sekHappyBool = false;
Assert.assertEquals(expectedEuroSum, euroSum);
Assert.assertEquals(expectedSekSum,sekSum);
if (eurHappy.equalsIgnoreCase("happy")) {
eurHappyBool = true;
}
if (sekHappy.equalsIgnoreCase("happy")) {
sekHappyBool = true;
}
Assert.assertEquals(eurHappyBool, intPriceList.get("coffee").isHappy());
Assert.assertEquals(sekHappyBool, intPriceList.get("donut").isHappy());
}
}
Class 价格是这样的:
package runsupport;
public class Price {
private String product;
private String currency;
private Integer price;
private boolean happy;
public Price(String product, Integer price, String currency){
this.product = product;
this.price = price;
this.currency = currency;
}
public String getProduct() {
return product;
}
public Integer getPrice() {
return price;
}
public String getCurrency() {
return currency;
}
public boolean isHappy() {
return happy;
}
}
考虑以下几点:
@Given("^this stuff:$")
public void this_stuff(List<ScenarioStuff> stuffList) throws Throwable {
stuffList.get(0).isHappy();
}
和特征:
Given this stuff:
|Name|
|Miguel|
最后,场景对象:
ScenarioStuff{
private String name;
private boolean happy;
(getters and setters for name and happy, inlcuding:)
public boolean isHappy(){
return happy;
}
这是我的发现:
- stuffList.get(0).isHappy();是假的;
- 即使
private boolean happy=true;
它仍然是错误的
ScenarioStuff(){ happy=true)
的默认构造函数仍然为 false
- 代码不会在该构造函数中使用断点中断。
问题:
如果未在功能 table 中作为参数提供,我如何默认 happy=true
?
Cucumber 使用 XStream to convert step definition arguments to Java objects, so to answer this we have to dig in XStream 的方法来做到这一点。
如 this answer to an XStream question 所述,一种选择是使用 readResolve 方法(如果可用,XStream 显然会使用它来设置对象。
在我的特殊情况下,将 happy 变量从 boolean
更改为 Boolean
后,我最终得到了如下实现:
ScenarioStuff{
private String Name;
private Boolean happy;
private Object readResolve() {
if(happy == null){
happy = true;
}
return this;
}
}
我还读到可以为 marshal/unmarshal 对象实现一个转换器,但我没有探索这个选项,因为 1) 它看起来不那么简单,并且 2) 我没有立即看到一个人会怎么做在黄瓜设置中注册这个新转换器。
更新 我添加了布尔值并让它们也起作用。
Scenario: An international coffee shop must handle currencies
Given the price list for an international coffee shop
| product | currency | price | happy |
| coffee | EUR | 1 | true |
| donut | SEK | 18 | false |
When I buy "1" "coffee" and "1" "donut"
Then I should pay "1" EUR be "happy" and "18" SEK be "unhappy"
步骤定义文件
public class datatable_steps {
private HashMap<String, Price> intPriceList = new HashMap<String, Price>();
private int sekSum;
private int euroSum;
@Given("^the price list for an international coffee shop$")
public void the_price_list_for_an_international_coffee_shop(List<Price> prices) {
int numPrices = prices.size();
System.out.println("numPrices = " + numPrices);
for(Price price : prices) {
String key = price.getProduct();
intPriceList.put(key, price);
}
}
@When("^I buy \"(\d+)\" \"(.*)\" and \"(\d+)\" \"(.*)\"$")
public void i_order_coffee_and_donut(int numberOfFirstItems, String firstItem,
int numberOfSecondItems, String secondItem) throws Throwable {
Price firstPrice = intPriceList.get(firstItem);
calculate(numberOfFirstItems, firstPrice);
Price secondPrice = intPriceList.get(secondItem);
calculate(numberOfSecondItems, secondPrice);
}
private void calculate(int numberOfItems, Price price) {
if (price.getCurrency().equals("SEK")) {
sekSum += numberOfItems * price.getPrice();
return;
}
if (price.getCurrency().equals("EUR")) {
euroSum += numberOfItems * price.getPrice();
return;
}
throw new IllegalArgumentException("The currency is unknown");
}
@Then("^I should pay \"(\d+)\" EUR be \"(.*)\" and \"(\d+)\" SEK be \"(.*)\"$")
public void should_I_pay_EUR_and_SEK(int expectedEuroSum, String eurHappy, int expectedSekSum, String sekHappy) throws Throwable {
boolean eurHappyBool = false;
boolean sekHappyBool = false;
Assert.assertEquals(expectedEuroSum, euroSum);
Assert.assertEquals(expectedSekSum,sekSum);
if (eurHappy.equalsIgnoreCase("happy")) {
eurHappyBool = true;
}
if (sekHappy.equalsIgnoreCase("happy")) {
sekHappyBool = true;
}
Assert.assertEquals(eurHappyBool, intPriceList.get("coffee").isHappy());
Assert.assertEquals(sekHappyBool, intPriceList.get("donut").isHappy());
}
}
Class 价格是这样的:
package runsupport;
public class Price {
private String product;
private String currency;
private Integer price;
private boolean happy;
public Price(String product, Integer price, String currency){
this.product = product;
this.price = price;
this.currency = currency;
}
public String getProduct() {
return product;
}
public Integer getPrice() {
return price;
}
public String getCurrency() {
return currency;
}
public boolean isHappy() {
return happy;
}
}