【发布时间】:2018-01-03 18:30:33
【问题描述】:
我是 Spock 的新手,这个问题指的是使用 Spock 进行 Java 测试的第 178 页上的示例。被测试的类是购物应用的Basket类,被测试的这个类的方法是canShipCompletely()
public class Basket {
private WarehouseIneventory warehouseInventory;
private ShippingCalculator shippingCalculator;
protected Map<Product, Integer> contents = new HashMap<>();
...
public void addProduct(Product product) {
addProduct(product, 1);
}
public void addProduct(Product product, int times) {
if (contents.containsKey(product)) {
int existing = contents.get(product);
contents.put(product, existing + times);
} else {
contents.put(product, times);
}
}
public Boolean canshipCompletely() {
if(warehouseInventory.isEmpty()) return false;
try {
for (Entry<Product, Integer> entry : contents.entrySet())
boolean ok = warehouseInventory.isProductAvailable(
entry.getKey().getName(),
entry.getValue()
);
if (!ok) {
return false;
}
}
return true;
} catch (Exception e) {
return false;
}
...
}
此方法 canShipCompletely() 循环遍历购物篮中的项目(在地图内容中),并且对于每个项目,它都会调用 warehouseInventory.isProductAvailable(product, count) 以查看仓库中是否有足够的库存来填充命令。 Warehouse 类是 Basket 类的协作者,在下面的测试中被模拟
def "Warehouse is queried for each product"() {
given: "a basket, a TV and a camera"
Product tv = new Product(name:"bravia",price:1200,weight:18)
Product camera = new Product(name:"panasonic",price:350,weight:2)
Basket basket = new Basket()
and: "a warehouse with limitless stock"
WarehouseInventory inventory = Mock(WarehouseInventory)
basket.setWarehouseInventory(inventory)
when: "user checks out two products"
basket.addProduct tv
basket.addProduct camera
boolean readyToShip = basket.canShipCompletely()
then: "order can be shipped"
readyToShip
2 * inventory.isProductAvailable( _ , _) >> true
0 * inventory.preload(_ , _)
}
then: 块验证布尔值 readyToShip 是否为真,并且 inventory.isProducAvailable() 被调用了两次,inventory.preload() 根本没有被调用。最后一行的下一行是检查模拟的行为并告诉它返回 true 以调用 isProductAvailable()。我不明白的是,如果我将模拟预定义响应移动到 and: 块,测试将失败,如下所示
def "Warehouse is queried for each product"() {
given: "a basket, a TV and a camera"
Product tv = new Product(name:"bravia",price:1200,weight:18)
Product camera = new Product(name:"panasonic",price:350,weight:2)
Basket basket = new Basket()
and: "a warehouse with limitless stock"
WarehouseInventory inventory = Mock(WarehouseInventory)
// ******** Move mock predefined response here **********
inventory.isProductAvailable( _ , _ ) >> true
basket.setWarehouseInventory(inventory)
when: "user checks out two products"
basket.addProduct tv
basket.addProduct camera
boolean readyToShip = basket.canShipCompletely()
then: "order can be shipped"
readyToShip
2 * inventory.isProductAvailable( _ , _)
0 * inventory.preload(_ , _)
}
我得到的失败是对 isProductAvailable() 的调用太少:
调用太少:
2 * inventory.isProductAvailable(_, _)(1 次调用)
不匹配的调用(按相似度排序):
1 * inventory.isEmpty()
我不明白为什么模拟的预定义行为不能移动到 and: 块。
【问题讨论】: