Я использую фабрики (см. http://www.php.net/manual/en/language.oop5.patterns.php для шаблона), чтобы повысить тестируемость нашего кода.Простая фабрика может выглядеть так:
class Factory
{
public function getInstanceFor($type)
{
switch ($type) {
case 'foo':
return new Foo();
case 'bar':
return new Bar();
}
}
}
Вот пример класса, использующего эту фабрику:
class Sample
{
protected $_factory;
public function __construct(Factory $factory)
{
$this->_factory = $factory;
}
public function doSomething()
{
$foo = $this->_factory->getInstanceFor('foo');
$bar = $this->_factory->getInstanceFor('bar');
/* more stuff done here */
/* ... */
}
}
Теперь для правильного модульного тестирования мне нужно смоделировать объект, который будет возвращать заглушкидля классов, и вот где я застрял.Я думал, что можно было бы сделать это так:
class SampleTest extends PHPUnit_Framework_TestCase
{
public function testAClassUsingObjectFactory()
{
$fooStub = $this->getMock('Foo');
$barStub = $this->getMock('Bar');
$factoryMock = $this->getMock('Factory');
$factoryMock->expects($this->any())
->method('getInstanceFor')
->with('foo')
->will($this->returnValue($fooStub));
$factoryMock->expects($this->any())
->method('getInstanceFor')
->with('bar')
->will($this->returnValue($barStub));
}
}
Но когда я запускаю тест, я получаю следующее:
F
Time: 0 seconds, Memory: 5.25Mb
There was 1 failure:
1) SampleTest::testDoSomething
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-bar
+foo
FAILURES!
Tests: 1, Assertions: 0, Failures: 1.
Так что, очевидно, невозможнопусть фиктивный объект возвращает разные значения в зависимости от переданных аргументов метода.
Как это можно сделать?