Skip to content

Instantly share code, notes, and snippets.

@jakzal
Last active September 26, 2018 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jakzal/23da90ee018c5f5c1927a67088a4c631 to your computer and use it in GitHub Desktop.
Save jakzal/23da90ee018c5f5c1927a67088a4c631 to your computer and use it in GitHub Desktop.
Test double examples
<?php declare(strict_types=1);
namespace App\Tests\Doubles;
use PHPUnit\Framework\TestCase;
class Item
{
}
interface Basket
{
/**
* @return Item[]
*/
public function items(): array;
public function add(Item $item): void;
}
class Foo
{
private $basket;
public function __construct(Basket $basket)
{
$this->basket = $basket;
}
public function a(): bool
{
return true;
}
public function b(): array
{
return $this->basket->items();
}
public function c(Item $item): void
{
$this->basket->add($item);
}
}
class DoublesTest extends TestCase
{
public function test_custom_dummy()
{
$basketDummy = new class implements Basket {
public function items(): array
{
}
public function add(Item $item): void
{
}
};
$foo = new Foo($basketDummy);
$this->assertTrue($foo->a());
}
public function test_prophecy_dummy()
{
$basketDummy = $this->prophesize(Basket::class);
$foo = new Foo($basketDummy->reveal());
$this->assertTrue($foo->a());
}
public function test_phpunit_dummy()
{
$basketDummy = $this->createMock(Basket::class);
$foo = new Foo($basketDummy);
$this->assertTrue($foo->a());
}
public function test_custom_stub()
{
$items = [new Item(), new Item()];
$basketStub = new class($items) implements Basket {
private $items;
public function __construct(array $items)
{
$this->items = $items;
}
public function items(): array
{
return $this->items;
}
public function add(Item $item): void
{
}
};
$foo = new Foo($basketStub);
$this->assertSame($items, $foo->b());
}
public function test_prophecy_stub()
{
$items = [new Item(), new Item()];
$basketStub = $this->prophesize(Basket::class);
$basketStub->items()->willReturn($items);
$foo = new Foo($basketStub->reveal());
$this->assertSame($items, $foo->b());
}
public function test_phpunit_stub()
{
$items = [new Item(), new Item()];
$basketStub = $this->createMock(Basket::class);
$basketStub->expects($this->any())
->method('items')
->willReturn($items);
$foo = new Foo($basketStub);
$this->assertSame($items, $foo->b());
}
public function test_custom_mock_object()
{
$item = new Item();
$basketMock = new class implements Basket {
public $addedItem;
public function items(): array
{
}
public function add(Item $item): void
{
$this->addedItem = $item;
}
public function __destruct()
{
if (null === $this->addedItem) {
throw new \LogicException('Expected "add" method to be called.');
}
}
};
$foo = new Foo($basketMock);
$foo->c($item);
}
public function test_prophecy_mock_object()
{
$item = new Item();
$basketMock = $this->prophesize(Basket::class);
$basketMock->add($item)->shouldBeCalled();
$foo = new Foo($basketMock->reveal());
$foo->c($item);
}
public function test_phpunit_mock_object()
{
$item = new Item();
$basketMock = $this->createMock(Basket::class);
$basketMock->expects($this->once())
->method('add')
->with($item);
$foo = new Foo($basketMock);
$foo->c($item);
}
public function test_custom_spy()
{
$item = new Item();
$basketSpy = new class implements Basket {
public $addedItem;
public function items(): array
{
}
public function add(Item $item): void
{
$this->addedItem = $item;
}
};
$foo = new Foo($basketSpy);
$foo->c($item);
$this->assertSame($item, $basketSpy->addedItem);
}
public function test_prophecy_spy()
{
$item = new Item();
$basketSpy = $this->prophesize(Basket::class);
$foo = new Foo($basketSpy->reveal());
$foo->c($item);
$basketSpy->add($item)->shouldHaveBeenCalled();
}
public function test_phpunit_spy()
{
// there is a way, but it’s ugly. Google “spying with phpunit"
}
public function test_fake_object()
{
$item = new Item();
$basketFake = new class implements Basket {
private $items = [];
public function items(): array
{
return $this->items;
}
public function add(Item $item): void
{
$this->items[] = $item;
}
};
$foo = new Foo($basketFake);
$foo->c($item);
$this->assertSame([$item], $foo->b());
}
public function test_prophecy_fake_object()
{
$item = new Item();
$basketFake = $this->prophesize(Basket::class);
$basketFake->add($item)->will(function ($args) {
$this->items()->willReturn([$args[0]]);
});
$foo = new Foo($basketFake->reveal());
$foo->c($item);
$this->assertSame([$item], $foo->b());
}
public function test_phpunit_fake_object()
{
$item = new Item();
$basketFake = $this->createMock(Basket::class);
$basketFake->method('add')
->with($item)
->will($this->returnCallback(function (Item $item) use ($basketFake) {
$basketFake->method('items')->willReturn([$item]);
}));
$foo = new Foo($basketFake);
$foo->c($item);
$this->assertSame([$item], $foo->b());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment