Reputation: 4175
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);
}
}
Upvotes: 2
Views: 4732
Reputation: 39380
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.
Upvotes: 7