Behat test below won't actually run $this->mySpecialService->getAttachment($pathToAttachment); service. It will pretend like it does. This is purely for testing reasons because in real life you might need to call external APIs which would be problem in tests so we mock it instead. It uses Symfony2 Mocker Extension library.


Install extension


Composer.json


Add "polishsymfonycommunity/symfony2-mocker-extension": "*" to your composer.json and run composer update polishsymfonycommunity/symfony2-mocker-extension command.


Behat.yml


default:
# ...
extensions:
PSS\Behat\Symfony2MockerExtension\Extension: ~

AppKernel.php


/**
* @return string
*/
protected function getContainerBaseClass()
{
if ('test' == $this->environment) {
return '\PSS\SymfonyMockerContainer\DependencyInjection\MockerContainer';
}

return parent::getContainerBaseClass();
}

Example controller


class MessageController extends AbstractController
{
/**
* @Method({"GET"})
* @Route("/orders/{orderId}/messages/{messageId}/attachments/{attachmentId}")
*
* @param int $orderId
* @param int $messageId
* @param int $attachmentId
*
* @return Response
*
* @throws HttpResponseException|NotFoundHttpException
*/
public function getMessageAttachmentAction($orderId, $messageId, $attachmentId)
{
try {
// Assuming that you did some work here

// Behat mocking mocks this part
$result = $this->mySpecialService->getAttachment($pathToAttachment);

if ($result->code != 200) {
throw new HttpResponseException(sprintf('Couldn\'t fetch image from [%s].', $pathToAttachment));
}

$response = new Response();
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', $attachmentContentType);
$response->headers->set('Content-Disposition', sprintf('attachment;filename=%s', $attachmentName));
$response->setStatusCode($result->code);
$response->sendHeaders();
$response->setContent($result->body);

return $response;
} catch (Exception $e) {
throw new NotFoundHttpException($e->getMessage());
}
}
}

Example scenario


Feature: Just testing

Scenario: I can download specific message attachment
Given the Mailgun API is available
Then I send a GET request to "/api/orders/1/messages/1/attachments/1"
And the response status code should be 200

FeatureContext


use PSS\Behat\Symfony2MockerExtension\Context\ServiceMockerAwareInterface;
use PSS\Behat\Symfony2MockerExtension\ServiceMocker;

class FeatureContext extends MinkContext implements ServiceMockerAwareInterface
{
/**
* @var ServiceMocker
*/
private $mocker;

public function setServiceMocker(ServiceMocker $mocker)
{
$this->mocker = $mocker;
}

/**
* @Given /^the My special API is available$/
*/
public function mySpecialApiIsAvailable()
{
$response['body'] = 'Binary string goes here';
$response['code'] = 200;


// application_backend.service.my_special_api is defined in your service.yml
// Application\BackendBundle\Service\MySpecialApi is class that deals with API
// getAttachment() is defined in MySpecialApi class and gets triggered in controller
$this->mocker->mockService('application_backend.service.my_special_api', 'Application\BackendBundle\Service\MySpecialApi')
->shouldReceive('getAttachment')
->once()
->andReturn((object) $response);
}
}

You could do like this as well. For more info, visit Mockery Docs.


class Whatever
{
public function apiRequestResponseMock()
{
$mockResponse = Mockery::mock('Guzzle\Http\Message\Response');
$mockResponse->shouldReceive('getBody')->with(true)->andReturn('I am the response body');

$mockRequest = Mockery::mock('Guzzle\Http\Message\Request');
$mockRequest->shouldReceive('send');
$mockRequest->shouldReceive('getResponse')->andReturn($mockResponse);
}
}