2

I'm trying to unit test my service, containing a dependency Finder Component of symfony2(http://symfony.com/doc/current/components/finder.html).

I'm getting :

[Exception] Objects returned by Mock_Finder_91776c5c::getIterator() must be traversable or implement interface Iterator

The service :

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 ?

    }

And the test

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);

    }

}

1 Answer 1

7

The mocked instance of the Finder class needs to implement/mock the method getIterator. The getMock method does not accept arguments so don't pass the string 'Iterator'—change the code as follows:

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

And add the Mocked expectation in the test method, for example:

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

Hope this helps.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.