Qafoo GmbH - passion for software quality

Help you and your team benefit from new perspectives on cutting-edge quality engineering techniques and tools through the Qafoo team weblog.

By Benjamin Eberlei, first published at Tue, 08 Mar 2016 10:30:00 +0100

Download our free e-book "Crafting Quality Software" with a selection of the finest blog posts as PDF or EPub.

Crafting Quality Software

You can also buy a printed version of the book on Amazon or on epubli.

Testing Effects of Commands With Phake::capture()

Today I want to share a simple trick for the excellent Mocking library Phake (I wrote about it before) when testing state on APIs that don't return values.

Testing becomes harder when you are using command / query separation in your code and service operations don't return values anymore. If your command method creates objects and passes them down the stack, then you usually want to make assertions on the nature of the changes.

Take the following example that creates a new Order object:

<?php class CheckoutHandler { private $orderRepository; private $productRepository; public function __construct($orderRepository, $productRepository) { $this->orderRepository = $orderRepository; $this->productRepository = $productRepository; } public function checkout(Checkout $command) { $order = new Order(); $order->setAddress($command->address); foreach ($command->productIds as $id => $amount) { $product = $this->productRepository->find($id); $order->addItem($product, $amount); } $this->orderRepository->save($order); } }

A "usual" PHPUnit test for this class can only make a single assertion that the OrderRepository is called with an Order object. But we might want know if a product was correctly assigned.

We can help you to set up continuous and automated testing for your projects. Book a workshop now.

With Phake::capture($value) we can assign the argument passed to OrderRepository#save($order) to a variable that is available inside the Unit-Test, ready to run assertions on.

<?php class CheckoutHandlerTest extends \PHPUnit_Framework_TestCase { public function testCheckout() { $orderRepository = \Phake::mock(OrderRepository::class); $productRepository = \Phake::mock(ProductRepository::class); $product = new Product(); \Phake::when($productRepository)->find(42)->thenReturn($product); $handler = new CheckoutHandler($orderRepository, $productRepository); $handler->checkout(new Checkout([ 'productIds' => [42 => 1], 'address' => new Address(), ])); \Phake::verify($orderRepository)->save(\Phake::capture($order)); $this->assertEquals(1, count($order->getProducts())); $this->assertSame($product, $order->getProducts()[0]); } }

See after the \Phake::capture($order) call, the $order variable contains the argument that was passed to the OrderRepository from your code.

This argueably reaches into the tested class quite a bit, but when you use Command / Query separation and London-Style TDD the only way to observe behaviour and state is mocking. I still think Phake is the best mocking library for PHP and the capture method is another good argument for it.

Download our free e-book "Crafting Quality Software" with a selection of the finest blog posts as PDF or EPub.

Crafting Quality Software

You can also buy a printed version of the book on Amazon or on epubli.

Get Technical Insights With Our Newsletter

Stay up to date with regular new technological insights by subscribing to our newsletter. We will send you articles to improve your developments skills.

Comments