testing - Predefined mock response in Spock -
i'm new spock , question refers example on page 178 of java testing spock. class under test basket class shopping application, , method of class being tested 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 { (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; } ... }
this method canshipcompletely() loops on items in basket (in map contents) , each item, makes call warehouseinventory.isproductavailable(product, count) see if there sufficient stock in warehouse fill order. warehouse class collaborator of basket class mocked in following test
def "warehouse queried each product"() { given: "a basket, tv , 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 limitless stock" warehouseinventory inventory = mock(warehouseinventory) basket.setwarehouseinventory(inventory) when: "user checks out 2 products" basket.addproduct tv basket.addproduct camera boolean readytoship = basket.canshipcompletely() then: "order can shipped" readytoship 2 * inventory.isproductavailable( _ , _) >> true 0 * inventory.preload(_ , _) }
the then: block verifies boolean readytoship true, , inventory.isproducavailable() called twice , inventory.preload() not called @ all. next last line both checking behavior of mock , telling return true calls isproductavailable(). don't understand test fail if move mock predefined response and: block follows
def "warehouse queried each product"() { given: "a basket, tv , 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 limitless stock" warehouseinventory inventory = mock(warehouseinventory) // ******** move mock predefined response here ********** inventory.isproductavailable( _ , _ ) >> true basket.setwarehouseinventory(inventory) when: "user checks out 2 products" basket.addproduct tv basket.addproduct camera boolean readytoship = basket.canshipcompletely() then: "order can shipped" readytoship 2 * inventory.isproductavailable( _ , _) 0 * inventory.preload(_ , _) }
the failure few calls isproductavailable():
too few invocations for:
2 * inventory.isproductavailable( _ , _) (1 invocation)
unmatched invocations (ordered similarity):
1 * inventory.isempty()
i don't understand why predefined behavior mock can't moved and: block.
please refer documentation
when mocking , stubbing same method call, have happen in same interaction. in particular, following mockito-style splitting of stubbing , mocking 2 separate statements not work:
setup: subscriber.receive("message1") >> "ok" when: publisher.send("message1") then: 1 * subscriber.receive("message1")
as explained in declare interactions, receive call first matched against interaction in then: block. since interaction doesn’t specify response, default value method’s return type (null in case) returned. (this facet of spock’s lenient approach mocking.). hence, interaction in setup: block never chance match.
Comments
Post a Comment