phpunit 必须是可遍历的或实现接口 Iterator

Xer*_*ero 2 phpunit mocking symfony

我正在尝试对我的服务进行单元测试,其中包含 symfony2 的依赖 Finder 组件(http://symfony.com/doc/current/components/finder.html)。

我越来越 :

[异常] Mock_Finder_91776c5c::getIterator() 返回的对象必须是可遍历的或实现接口 Iterator

服务 :

public function getFile($fileName, $path = '/')
    {

        if($this->wrapper == null || $this->connection == null)
            throw new LogicException("call method setFTP first");

        // get file on ftp server
        $this->connection->open();
        $downloadComplete = $this->wrapper->get($this->tmpDir . $fileName, $path . $fileName);
        $this->connection->close();

        if($downloadComplete == false)
            return false; // TODO exception ?

        // return file downloaded
        $this->finder->files()->in(__DIR__);
        foreach ($this->finder as $file) {
            return $file;
        }

        return false; // TODO exception ?

    }
Run Code Online (Sandbox Code Playgroud)

和测试

class FtpServiceTest extends \PHPUnit_Framework_TestCase
{

    protected $connectionMock;
    protected $ftpWrapperMock;
    protected $finderMock;

    protected function setUp()
    {
        $this->connectionMock = $this->getConnectionMock();
        $this->ftpWrapperMock = $this->getFTPWrapperMock();
        $this->finderMock = $this->getFinderMock();
    }

    protected function tearDown()
    {
    }

    private function getFinderMock()
    {
        return $this->getMockBuilder(Finder::class)
            ->disableOriginalConstructor()
            ->getMock('Iterator');
    }

    private function getConnectionMock()
    {
        return $this->getMockBuilder(Connection::class)
            ->disableOriginalConstructor()
            ->getMock();
    }

    private function getFTPWrapperMock()
    {
        return $this->getMockBuilder(FTPWrapper::class)
            ->disableOriginalConstructor()
            ->getMock();
    }

    // tests
    public function testMe()
    {

        // arrange
        $host = 'localhost';
        $user = 'user';
        $password = '1234';

        $filesArray = new ArrayObject(array(''));

        $service = new FtpService('var/tmp/');
        $service->setFTP($this->connectionMock, $this->ftpWrapperMock);
        $service->setFinder($this->finderMock);

        $this->connectionMock
            ->expects($this->once())
            ->method('open');

        $this->ftpWrapperMock
            ->expects($this->once())
            ->method('get')
            ->will($this->returnValue(true));

        $this->connectionMock
            ->expects($this->once())
            ->method('close');

        $this->finderMock
            ->expects($this->once())
            ->method('files')
            ->will($this->returnValue($this->finderMock));

        $this->finderMock
            ->expects($this->once())
            ->method('in')
            ->will($this->returnValue($filesArray));

        // act
        $file = $service->getFile('/file.zip');

        // assert
        $this->assertInstanceOf(SplFileInfo::class, $file);

    }

}
Run Code Online (Sandbox Code Playgroud)

Mat*_*teo 6

Finder类的模拟实例需要实现/模拟方法getIterator。该getMock方法不接受参数,因此不要传递字符串 -'Iterator'更改代码如下:

private function getFinderMock()
{
    return $this->getMockBuilder(Finder::class)
        ->disableOriginalConstructor()
        ->getMock();
}
Run Code Online (Sandbox Code Playgroud)

并在测试方法中添加 Mocked 期望,例如:

    $this->finderMock->expects($this->once())
        ->method('getIterator')
        ->willReturn(new \ArrayObject([$this->createMock(SplFileInfo::class)]));
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。