Stub Test Double Using Prophecy
Stub is the next simplest test double after the Dummy.
It doesn't have any expectations about the object behavior, but behaves in a specific way when put in a specific environment.
Below is the class under the test:
<?php
namespace App;
class Questioner
{
private $output;
private $questions = [];
public function __construct(OutputInterface $output)
{
$this->output = $output;
}
/** @return int */
public function getQuestionsCount()
{
return 0;
}
/**
* Save under a new name.
*
* @param string $name
* @return boolean
*/
public function saveAs($name)
{
return $this->output->save($this->questions, $name);
}
}
saveAs
method can be tested by using a stub test double:
<?php
namespace tests;
use App\Output;
use App\Questioner;
class QuestionerTest extends \PHPUnit_Framework_TestCase
{
/**
* @test
*/
function new_questioner_has_no_questions()
{
$outputDummy = $this->prophesize(Output::class);
$questioner = new Questioner($outputDummy->reveal());
$this->assertSame(0, $questioner->getQuestionsCount());
}
/**
* @test
*/
function questioner_is_saved_under_a_new_name()
{
$outputStub = $this->prophesize(Output::class);
$outputStub->save([], 'new name')->willReturn(true);
$questioner = new Questioner($outputStub->reveal());
$this->assertTrue($questioner->saveAs('new name'));
}
}
The test will pass as long as first parameter for save
method is an empty array ([]
) and the second parameter is new name
. Prophecy allows you to use argument wildcards making your tests more durable. Below you can see a new test which allows any string for a name:
<?php
// ...
use Prophecy\Argument;
class QuestionerTest extends \PHPUnit_Framework_TestCase
{
// ...
/**
* @test
*/
function questioner_is_saved_under_any_name()
{
$outputStub = $this->prophesize(Output::class);
$outputStub->save([], Argument::type('string'))->willReturn(true);
$questioner = new Questioner($outputStub->reveal());
$this->assertTrue($questioner->saveAs('any name'));
}
}
For the full list of arguments you can you check the code of Prophecy\Argument
class. Here's some of them you might want to use in your tests:
Argument::is($value)
checks that the argument is identical to a specific valueArgument::exact($value)
checks that the arguments matches a specific valueArgument::type($typeOrClass)
checks that the argument matches a specific type or class nameArgument::any()
matches any argument
This article is from the Test doubles using Prophecy series which is made from following articles: