What is the proper way to run an integration test for Slim 3 and Phpunit?


#1

Hi!

I am writing an app with Slim 3 at the moment.
Can you show an example of a proper integration test using Phpunit?
It’s being said that subRequest is not here to stay. What is the proper way of executing and mocking requests?

I set route handlers as callables like this:

$this->get('/', function (RequestInterface $request, ResponseInterface $response, array $args) {
                ///   ...                
                return $response;                
})->setName('api.notes');

There is something else I wanted to ask.
When I call this code:

$response = $app->subRequest(
            $method,
            $path,
            '',
            $headers,
            [],
            json_encode($data)
);

This http call is supposed to fail and return 500 error response, but what I get is exception that bubbled up to the testing code, rather than to Slim error handler. Why is that so?


#2

I did some research and, I believe, here is how one should write integration tests:
I created two helper methods one for making request object, another to call slim app and return response object.

// 1. Prepare the request object with all the required data:
protected function getRequest(string $method, string $path, array $data = [])
    {
        $method = strtoupper($method);
        
        $request = Request::createFromEnvironment(Environment::mock([
            'REQUEST_METHOD' => strtoupper($method),
            'REQUEST_URI' => $path,
            'QUERY_STRING' => ($method == "GET") ? http_build_query($data) : "",
        ]));
        
        $request = $request->withHeader('Content-Type', 'application/json');
        
        if ($method == "POST") {
            $request->getBody()->write(json_encode($data));
        }
            
        return $request;
    }

// 2. call process() on slim app instance
protected function sendHttpRequest(
        RequestInterface $request,
        App $app = null
    ): Response {
        
        if (!$app) {
            $app = container()->get(App::class);
        }
        
        $response = $app->process($request, new Response());
        
        return $response;
    }

// 3. then run assertions on Response object
// Complete test would look like this:
$request  = $this->getRequest("get", "/some");
$response = $this->sendHttpRequest($request, $app);
$this->assertEquals(200, $response->getStatusCode());

#3

This was required in order for middleware to be called, FYI. I was unable to figure out why JWT was never run until I found this post.


#4

I strongly believe that documentation must contain a section of best testing practices for this framework. As of now, https://www.slimframework.com/docs/ has no such topic and that is a thing to think about.


#5

There is an article about testing slim framework actions you may find helpful.