To test a Slim Framework action, you need a request and a response object and mock whatever is in the action. This is one way to do this.

Consider this simple echo action that returns the query parameters to you as a JSON encoded string:

$ curl "http://localhost:8888/echo?foo=bar&this=that"
{"foo":"bar","this":"that"}

This is one of those useful API endpoints that your users can use to check that everything is working as expected.

The action under test

The code for this endpoint is a class called EchoAction which looks like this:

namespace AppAction;

use PsrHttpMessageServerRequestInterface as Request;
use PsrHttpMessageResponseInterface as Response;

class EchoAction
{
    public function __invoke(Request $request, Response $response, $args = [])
    {
        return $response->withJson($request->getQueryParams());
    }
}

and it is registered with the Slim App like so:

$app->get('/echo', AppActionEchoAction::class);

Testing

Testing it isn’t too complex as there are no dependencies on the EchoAction class itself, so we just have instantiate the class, invoke it and write an test.

For a URL of the form /echo?foo=bar, the core test code is:

$action = new AppActionEchoAction();
$response = $action($request, $response);
$this->assertSame((string)$response->getBody(), json_encode(['foo' => 'bar']));

Creating the request and response

Creating the $response is easy as the constructor parameters all have defaults:

$response = new SlimHttpResponse();

The $request is a little more complex as it’s constructor signature looks like this:

public function __construct(
        $method,
        UriInterface $uri,
        HeadersInterface $headers,
        array $cookies,
        array $serverParams,
        StreamInterface $body,
        array $uploadedFiles = []
    )

However, Slim actually creates a SlimHttpRequest using the static createFromEnvironment() factory method, which takes a SlimHttpEnvironment instance. Roughly, it does this:

$request = Request::createFromEnvironment(new Environment($_SERVER));

Setting up a $_SERVER array with the relevant elements can be a little tiresome in testing though. Fortunately, Josh needed to test Slim itself, so the Environment object has a handy static method called mock() that does this for us.

We use it like this:

$environment = SlimHttpEnvironment::mock([
    'REQUEST_METHOD' => 'GET',
    'REQUEST_URI' => '/echo',
    'QUERY_STRING'=>'foo=bar'
]);

As you can see, mock() takes an array which contains $_SERVER keys that we wish to set up for our particular test. Usually we set the REQUEST_METHOD, REQUEST_URI and, if we need it, QUERY_STRING. We need QUERY_STRING as this is the key in $_SERVER that Request uses to determine the query parameters for the request.

Putting it all together

Hence, our completed test looks like this:

class EchoActionTest extends PHPUnit_Framework_TestCase
{
    public function testGetRequestReturnsEcho()
    {
        // instantiate action
        $action = new AppActionEchoAction();

        // We need a request and response object to invoke the action
        $environment = SlimHttpEnvironment::mock([
            'REQUEST_METHOD' => 'GET',
            'REQUEST_URI' => '/echo',
            'QUERY_STRING'=>'foo=bar']
        );
        $request = SlimHttpRequest::createFromEnvironment($environment);
        $response = new SlimHttpResponse();

        // run the controller action and test it
        $response = $action($request, $response, []);
        $this->assertSame((string)$response->getBody(), '{"foo":"bar"}');
    }
}

All in all, it’s not too complicated to test a Slim action and Environment::mock() makes it easy to set up particular test cases.

Source: AKRABAT

By Rob