Как имитировать объектную фабрику

Я часто использую Фабрики (см. 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.

Очевидно, что невозможно позволить фиктивному объекту возвращать разные значения в зависимости от переданного метода аргументы таким образом.

Как это можно сделать?

6
задан edorian 10 January 2012 в 15:19
поделиться