mardi 28 juillet 2015

PHPUnit: How to test the downloading of a file with Guzzle

I'm trying to unit test an Image entity that, using \GuzzleHttp\Client, downloads an image from a remote URL and stores it on the local filesystem.

The method is this and is taken, with some changes, from the Symfony documentation about how to upload a file, where it is called upload().

I've done some editings, as the signature, where a client is required to be passed (to decouple the class from the client to be able to unit test it).

/**
 * @param Client $client The client to use to download the image
 */
public function download(Client $client)
{
    // set the path property to the filename where you've saved the file
    $this->path = $this->getDownloadDir();

    // Get the remote file extension
    $remoteImageExtension = explode('.', $this->getRemoteUri()->getPath());
    $remoteImageExtension = array_pop($remoteImageExtension);
    $fs = new Filesystem();

    $tempImage = tempnam(sys_get_temp_dir(), 'image.') . '.' . $remoteImageExtension;

    // Get and save file
    $client->get($this->getRemoteUri(), ['save_to' => $tempImage]);

    $tempImage = new File($tempImage);

    $this->name = $this->getName() . '.' . $remoteImageExtension;
    $newImage = $this->getDownloadRootDir() . $this->getName();

    $fs->copy($tempImage, $newImage);
}

As you can see the method uses the client to download the image and save it to a local temp folder.

My question is: which file should have I to pass to the client?

In my tests I mock the GuzzleHttp\Client class and set the method $client->get() to return simply true.

But the entity throws an exception, because it makes use of File that requires a real file passed (download from the remote URL).

So, I think I have to pass the URL of a real remote file, but doing so seems to me something to avoid.

How can I test this method?

I've also tried to use a temp image in this way:

    $image = new Image();

    $mockClient = $this->getMockBuilder('\GuzzleHttp\Client')
        ->disableOriginalConstructor()
        ->getMock();
    $mockClient->method('get')
        ->will($this->returnValue(true));

    $mockUri = $this->getMockBuilder('\SerendipityHQ\Framework\ValueObjects\Uri\Uri')
        ->disableOriginalConstructor()
        ->getMock();
    $fakeRemoteUri = tempnam(sys_get_temp_dir(), 'image') . '.jpg';
    $mockUri->method('getPath')
            ->will($this->returnValue($fakeRemoteUri));

    $image->setName(rand(0, 100))
        ->setCreatedOn(new \DateTime())
        ->setModifiedOn(new \DateTime())
        ->setRemoteUri($mockUri)
        ->setDownloadDir('path/to/download')
        ->download($mockClient);

This returns me:

Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException: The file "/private/var/folders/s5/wwsxvmxd025ctwf0ywwqf83c0000gn/T/image.NW4jvT./private/var/folders/s5/wwsxvmxd025ctwf0ywwqf83c0000gn/T/imagemf9ZPrjpg" does not exist

Aucun commentaire:

Enregistrer un commentaire