Another benefit of the stub mapping in Phake is that it allows you to very easily stub multiple calls to the same
method that use different parameters. In my shopping cart I have decided to add some functionality that will allow
me to easily add multiple products that are a part of a group to the shopping cart. To facilitate this I have decided
to create a new class called ItemGroup. The ItemGroup object will be
constructed with an array of Items. It will have a method on the class that will add all of
the items in the group to the given cart and then the total price of items in the cart will be returned.
It should be noted that earlier I decided to make a small change to the ShoppingCart::addItem()
method to have it return the total price of items in the cart. I figured that this would be nice api level functionality
to make working with the system a little bit easier. I would like to take advantage of that change with this code.
Here's a stub of the functionality I am considering.
Example 2.9.
<?php /** * A group of items that can be added to a cart all at the same time */ class ItemGroup { /** * @param array $items an array of Item objects */ public function __construct(array $items) { } /** * @param ShoppingCart $cart * @return money The new total value of the cart */ public function addItemsToCart(ShoppingCart $cart) { } } ?>
The next test I am going to write now is going to be focusing on this new ItemGroup::addItemsToCart()
method. In my test's setUp() method I'll create a new instance of ItemGroup
which will require one or more Item implementations. I'll use mocks for those. Then the actual
test case I am going to start with will be a test to assert that ItemGroup::addItemsToCart()
returns the new shopping cart value. I already know that I am going to need to get this value by looking at the
last return value from calls to ShoppingCart::addItem(). To allow for checking this I will mock
ShoppingCart and create three stubs for ShoppingCart::addItem(). Each
stub will be for a call with a different Item.
Example 2.10.
<?php class ItemGroupTest extends PHPUnit_Framework_TestCase { private $itemGroup; private $item1; private $item2; private $item3; public function setUp() { $this->item1 = Phake::mock('Item'); $this->item2 = Phake::mock('Item'); $this->item3 = Phake::mock('Item'); $this->itemGroup = new ItemGroup(array($this->item1, $this->item2, $this->item3)); } public function testAddItemsToCart() { $cart = Phake::mock('ShoppingCart'); Phake::when($cart)->addItem($this->item1)->thenReturn(10); Phake::when($cart)->addItem($this->item2)->thenReturn(20); Phake::when($cart)->addItem($this->item3)->thenReturn(30); $totalCost = $this->itemGroup->addItemsToCart($cart); $this->assertEquals(30, $totalCost); } } ?>
In this example the ShoppingCart::addItem() method is being stubbed three times. Each time it
is being stubbed with a different parameter being passed to addItem(). This a good example of
how parameters are also checked whenever Phake looks at a mock object's stub map for answers. The default behavior
of argument matching is again a loose equality check. Similar to how you would use the double equals operator in PHP.
The other options for argument matching are discussed further in Chapter 5, Method Parameter Matchers.