Integration testing helpers for the Slim Framework

Overview

Slim Test Helpers Build Status Code Climate Test Coverage

Integration testing helpers for the Slim Framework 3

For a full example, please see the companion repo at there4/slim-unit-testing-example.

Example

Here's a test for a very simple endpoint that returns the version from the application config. We're asserting that Slim responded with a 200 and that the version matches what we expect.

class VersionTest extends LocalWebTestCase
{
    public function testVersion()
    {
        $this->client->get('/version');
        $this->assertEquals(200, $this->client->response->getStatusCode());
        $this->assertEquals($this->app->config('version'), $this->client->response->getBody());
    }
}

Here is an example on how to pass data to a POST endpoint in a test case and retrieve it later in the endpoint. We are passing encoded JSON data in the body of the request. The data is retrieved in the endpoint using $app->request->getBody().

// test file
class UserTest extends LocalWebTestCase
{
    public function testVersion()
    {
        ......
        $data = array("user" => 1);
        $data = json_encode($data);
        $this->client->post('/user', $data);
        ......
    }
}

// endpoint file
.....
$app->post('/user', function() use ($app) {
    .....
    $data = $app->request->getBody();
    $data = json_decode($data, true);
    ......
});

Example with DbUnit

If you wish to use Database fixture, use class WebDbTestCase. Caution: Make sure the names you use for you fixture models won't conflict with your actual DB tables.

class LocalDbWebTestCase extends \There4\Slim\Test\WebDbTestCase
{
    /**
     * You must implement this method
     * @return PHPUnit_Extensions_Database_DataSet_IDataSet
     */
    public function getDataSet()
    {
        return $this->createFlatXMLDataSet(
            dirname(__FILE__) . DIRECTORY_SEPARATOR . 'fixture.xml'
        );
    }
}

Setup

You'll need a bootstrap file for phpunit that can instantiate your Slim application. You can see [an example boostrap] in the sample app.

You'll implement your own getSlimInstance() method that returns an instance of your app by extending the WebTestCase helper.

Comments
  • Repeated GET responses return empty body, 200 when they should 404

    Repeated GET responses return empty body, 200 when they should 404

    I'm using this library to do testing on my SLIM-based site. I have noticed that under some circumstances, the responses coming back from a GET request will be incorrect when run repeatedly.

    For instance, the first response from this will function as expected:

     $this->client->get('/topic/appetites/rss');
     $body = $this->client->response->getBody();
    

    And $body contains the expected information.

    However, if you run this:

     $this->client->get('/topic/education/rss');
     $body = $this->client->response->getBody();
    

    $body will be empty.

    A similar thing happens when testing the status of responses. If the preceding responses were a 200, a subsequent response that you'd expect to be a 404 will return 200. But, if you put that 404 before the 200s, it will properly return a 404.

    I think this has something to do with the output buffering (oh fun!), but I haven't been able to figure it out yet. I'm posting this in the hopes that someone else has seen the issue and has some thoughts. I'm not expecting anyone to fix this for me and I hope to be able to dig into it further in the near future.

    opened by justinph 10
  • Support phpunit 5

    Support phpunit 5

    Hi,

    I'm upgrading to php 7 in my slim project and my unit testing can't work with scalar type hinting and returning types because that's only supported in phpunit 5.*

    Is there a possibility to migrate and support phpunit 5.*?

    Thanks

    pr-requested 
    opened by khrizt 7
  • POST variables missing

    POST variables missing

    I am facing this weird problem.

    I have wrote the following test.

     public function testGetTaskGroup()
     {
       $this->client->get('/task/group');
       $this->assertEquals(200, $this->client->response->status());
       $results = json_decode($this->client->response->body(), true);
     }
    
     public function testCreateTaskGroupItem()
     {
       $data = array(
          "name" => "first_task"
       );
       $this->client->post('/task/group', $data);
       $this->assertEquals(200, $this->client->response->status());
       $results = json_decode($this->client->response->body(), true);
     }
    
    

    The POST variables in '/task/group' endpoint is missing when I retrieve it through $app->request->post() or $app->request->params() but if I comment out testGetTaskGroup, the variables for POST are appearing inside '/task/group' endpoint.

    Any idea why this is happening? Thanks.

    opened by jagandecapri 7
  • Fix Issue #34: Testing 'Internal Server Error (500)'

    Fix Issue #34: Testing 'Internal Server Error (500)'

    PHPUnit Ok!

    PHPUnit 5.5.2 by Sebastian Bergmann and contributors.
    
    ..................                                                18 / 18 (100%)
    
    Time: 266 ms, Memory: 10.00MB
    
    OK (18 tests, 34 assertions)
    
    opened by Starli0n 6
  • Replace __call with explicit method declarations

    Replace __call with explicit method declarations

    This commit will replace the __call magic with explicit method declarations for faking any of the supported HTTP methods.

    As a API, it's preferable for the API to be discoverable. Having explicit method declarations help IDEs to list the class methods when writing tests.

    opened by adbre 6
  • Support PHP 5.5

    Support PHP 5.5

    Since Slim 3 itself supports PHP 5.5, it would be great if this package could do so as well. PHP 5.5 is still fairly common.

    Unless there is a good reason to require PHPUnit 5 only (#30), I suggest supporting both 4 and 5. The unit tests still go green.

    Note: I added composer.lock to .gitignore – this way the Travis tests will always run against the latest versions matching the criteria, which I think is generally more useful, but I can remove that commit if you prefer to have it under version control. I also removed minimum-stability=dev.

    opened by danmichaelo 3
  • Fix #15 - allow to run multiple requests in the same test

    Fix #15 - allow to run multiple requests in the same test

    It turns out (at least in Slim 2.6) that the request (and the response) are a singleton in the Slim app. Thus even when mocking a new \Slim\Environment like the WebTestclient does, you'll always get the previous request that points to the previous environment (and thus the previous endpoint).

    The idea is to create fresh request and response object on every client call, and also override the matched route cache that is built into the router.

    opened by masterzen 3
  • Make WebTestCase abstract

    Make WebTestCase abstract

    PHPUnit includes files automatically which are non-abstract and tries to run tests. Thus, in our specific case we get an error on the WebTestCase file saying that "not tests are defined in WEbTestCase".

    This commit should solve that issue.

    opened by nover 3
  • Support GET request

    Support GET request

    It seems that WebTestClient doesn't support GET request, so I changed it.

    versions:

    • php: PHP 5.4.30
    • there4/slim-test-helpers: master
    • codeguy/Slim: 2.4.3

    I create this test case:

    <?php
    
    use Slim\Slim;
    use There4\Slim\Test\WebTestCase;
    
    class SampleTest extends WebTestCase
    {
        /**
         * @inheritdoc
         */
        public function getSlimInstance()
        {
            $app = new Slim(array(
                'debug' => false,
            ));
    
            // GET /messages
            $app->get('/messages', function() use ($app) {
                $request = $app->request();
                $user_id = $request->get('user_id');
    
                echo 'user_id:' . $user_id;
            });
    
            // POST /messages
            $app->post('/messages', function() use ($app) {
                $request = $app->request();
                $message = $request->post('message');
    
                echo 'message:' . $message;
            });
    
            return $app;
        }
    
        /**
         * @test
         */
        public function testPost()
        {
            $this->client->post('/messages', [
                'message' => 'hogehoge',
            ]);
            $this->assertSame('message:hogehoge', $this->client->response->getBody());
        }
    
        /**
         * @test
         */
        public function testGet()
        {
            $this->client->get('/messages', [
                'user_id' => 1234,
            ]);
            $this->assertSame('user_id:1234', $this->client->response->getBody());
        }
    }
    

    And execute this test with phpunit.

    Test Result

    Before:

    .F
    
    Time: 79 ms, Memory: 6.75Mb
    
    There was 1 failure:
    
    1) SampleTest::testGet
    Failed asserting that two strings are identical.
    --- Expected
    +++ Actual
    @@ @@
    -user_id:1234
    +user_id:
    

    After:

    ..
    
    Time: 75 ms, Memory: 6.75Mb
    
    OK (2 tests, 2 assertions)
    
    opened by cw-tanaka 3
  • Update README.md with POST endpoint example

    Update README.md with POST endpoint example

    README.md is updated with an example explaining on how to pass data to a POST endpoint in the request's body and how to retrieve it later in the endpoints.

    opened by jagandecapri 2
  • Response body is not returned anymore

    Response body is not returned anymore

    Since e2674fcac8f2873a4ccd027a333ff1a7e720841c calling get, post (or any other methods) doesn't return the HTTP response body as it used to do with __call.

    This breaks some of our tests :(

    PR will be sent soon.

    opened by masterzen 1
  • 2.1.2 is not strictly backwards compatible

    2.1.2 is not strictly backwards compatible

    Ouch, just discovered that my tests broke after upgrading from 2.1.1 to 2.1.2. Turned out to be two issues:

    1. The first issue was that my middleware mock broke. Quite subtle, but turns out that the use of process() over __invoke() introduced in #35 caused this to happen:
    Slim Application Error:
    Type: UnexpectedValueException
    Message: Middleware must return instance of \Psr\Http\Message\ResponseInterface
    File: /vagrant/vendor/slim/slim/Slim/MiddlewareAwareTrait.php
    Line: 75
    Trace: #0 /vagrant/vendor/slim/slim/Slim/MiddlewareAwareTrait.php(123): Slim\App->Slim\{closure}(Object(Slim\Http\Request), Object(Slim\Http\Response))
    #1 /vagrant/vendor/slim/slim/Slim/App.php(370): Slim\App->callMiddlewareStack(Object(Slim\Http\Request), Object(Slim\Http\Response))
    #2 /vagrant/vendor/there4/slim-test-helpers/src/There4/Slim/Test/WebTestClient.php(107): Slim\App->process(Object(Slim\Http\Request), Object(Slim\Http\Response))
    #3 /vagrant/vendor/there4/slim-test-helpers/src/There4/Slim/Test/WebTestClient.php(38): There4\Slim\Test\WebTestClient->request('get', '/api/auth/login', Array, Array)
    #4 /vagrant/tests/integration/AuthTest.php(7): There4\Slim\Test\WebTestClient->get('/api/auth/login')
    #5 [internal function]: AuthTest->testLoginRoute()
    #6 /vagrant/vendor/phpunit/phpunit/src/Framework/TestCase.php(909): ReflectionMethod->invokeArgs(Object(AuthTest), Array)
    #7 /vagrant/vendor/phpunit/phpunit/src/Framework/TestCase.php(768): PHPUnit_Framework_TestCase->runTest()
    #8 /vagrant/vendor/phpunit/phpunit/src/Framework/TestResult.php(612): PHPUnit_Framework_TestCase->runBare()
    #9 /vagrant/vendor/phpunit/phpunit/src/Framework/TestCase.php(724): PHPUnit_Framework_TestResult->run(Object(AuthTest))
    #10 /vagrant/vendor/phpunit/phpunit/src/Framework/TestSuite.php(722): PHPUnit_Framework_TestCase->run(Object(PHPUnit_Framework_TestResult))
    #11 /vagrant/vendor/phpunit/phpunit/src/Framework/TestSuite.php(722): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult))
    #12 /vagrant/vendor/phpunit/phpunit/src/TextUI/TestRunner.php(440): PHPUnit_Framework_TestSuite->run(Object(PHPUnit_Framework_TestResult))
    #13 /vagrant/vendor/phpunit/phpunit/src/TextUI/Command.php(149): PHPUnit_TextUI_TestRunner->doRun(Object(PHPUnit_Framework_TestSuite), Array)
    #14 /vagrant/vendor/phpunit/phpunit/src/TextUI/Command.php(100): PHPUnit_TextUI_Command->run(Array, true)
    #15 /vagrant/vendor/phpunit/phpunit/phpunit(52): PHPUnit_TextUI_Command::main()
    #16 {main}
    View in rendered output by enabling the "displayErrorDetails" setting.
    

    To fix this, I made a slightly more complicated mock. Would have been better if there was a way to disable all middleware. Didn't find one, but I wouldn't be surprised if it exists..

    1. The second issue was more directly related to #35. I had a test that catched RuntimeException triggered by 500 errors that I had to rewrite: https://github.com/danmichaelo/croptool/commit/098b95dc262695395c78d8f9bdceab749eba08b7

    While these two issues are not likely to bite many users, I wonder if the best would be to delete the 2.1.2 release and release it as 3.0.0 instead?

    opened by danmichaelo 0
  • First example is incorrect

    First example is incorrect

    When trying the same as the first example you have in your README.md file, calling $this->client->response->getBody()->getContent() returns "" in my test meaning the following does not work:

    $this->client->get('/');
    $this->assertEquals('Hello World', $this->client->response->getBody());
    

    Your example code:

    class VersionTest extends LocalWebTestCase
    {
        public function testVersion()
        {
            $this->client->get('/version');
            $this->assertEquals(200, $this->client->response->getStatusCode());
            $this->assertEquals($this->app->config('version'), $this->client->response->getBody());
        }
    }
    

    We have our own version (replicated) of WebTestCase as we have our own config and setup process.

    To get it working, our test make-up is the following:

        public function testHomePage()
        {
            $body = $this->client->get('/');
            $this->assertEquals(200, $this->client->response->getStatusCode());
            $this->assertContains('Hello world', $body);
            $this->assertContains('<title>Welcome</title>', $body);
        }
    

    The main difference with mine is that I am assigning $body = $this->client->get('/'); as ::get calls ::request but ends with return (string)$this->response->getBody();.

    Am I missing something or have the docs not been updated? I can PR on the fix in the docs providing I am not missing something first.

    opened by NigelGreenway 4
  • How to test 'Internal Server Error' from a LocalWebTestCase

    How to test 'Internal Server Error' from a LocalWebTestCase

    Hi,

    I would like to test an 'Internal Server Error' from a LocalWebTestCase but I do not know how to do it.

    First I added this error handler in SlimApp:

    // Error handler
    $container['errorHandler'] = function ($c) {
        return function ($request, $response, $exception) use ($c) {
            $c->logger->error('Internal Server Error');
            $data = array('message' => 'Internal Server Error');
            return $c['response']->withJson($data, 500);
        };
    };
    

    I added a specific route only for testing purpose:

    // Route for testing server internal error (ie: $container['errorHandler'])
    $app->get('/internalerror', function ($request, $response, $args) {
        $this->logger->info("Route '/' internalerror");
        throw new \Exception('Testing /internalerror.');
        return $response;
    });
    

    In a test case I do:

    public function testInternalError()
    {
        try {
            $this->client->get('/internalerror');
        } catch (\Exception $e) {
        }
        $response = $this->client->response;
        $this->assertEquals(500, $response->getStatusCode());
        $this->assertEquals('Internal Server Error', $response->getReasonPhrase());
        $this->assertEquals('application/json;charset=utf-8', $response->getHeader('Content-Type')[0]);
        $data = json_decode($response->getBody());
        $this->assertEquals('Internal Server Error', $data->message);
    }
    

    But $this->client->response return null.

    My aim would be to test the message sent by the server defined in the error handler.

    In a production environment, this route is working fine and I have the message 'Internal Server Error' in json.

    http://localhost:8080/internalerror

    {"message":"Internal Server Error"}
    

    Thanks for your help!

    opened by Starli0n 6
  • ErrorException: Undefined index: REQUEST_METHOD

    ErrorException: Undefined index: REQUEST_METHOD

    Hi,

    I'm trying to build a integration test suite in my project and with a simple test for a get query I get the following error

    ErrorException: Undefined index: REQUEST_METHOD
    
    /path/vendor/slim/slim/Slim/Environment.php:124
    /path/vendor/slim/slim/Slim/Environment.php:76
    /path/vendor/slim/slim/Slim/Slim.php:159
    /path/vendor/slim/slim/Slim/Helper/Set.php:228
    /path/vendor/slim/slim/Slim/Helper/Set.php:88
    /path/vendor/slim/slim/Slim/Slim.php:234
    /path/vendor/slim/slim/Slim/Slim.php:674
    /path/vendor/slim/slim/Slim/Middleware/MethodOverride.php:78
    /path/src/Middleware/ApiAuthorization.php:57
    /path/vendor/slim/slim/Slim/Slim.php:1302
    /path/public/index.php:80
    /path/Test/BaseTestCase.php:21
    /path/vendor/there4/slim-test-helpers/src/There4/Slim/Test/WebTestCase.php:19
    
    $this->client->get('/v1/users/fake', array(), $this->getAuthHeader());
    $this->assertEquals(200, $this->client->response->status());
    $this->assertEquals(array(), $this->client->response->body());
    

    I don't know if I need to do something more, this is my getSlimInstance method:

            $testSettings = array(
                'version'        => '0.0.0',
                'debug'          => false,
                'mode'           => 'testing',
            );
            $settings = include __DIR__.'/../config/settings.php';
            $settings = array_merge($settings, $testSettings);
            $app = new \Slim\Slim($settings);
    

    Did I forgot about something?

    Thanks

    opened by khrizt 1
Releases(v2.1.3)
Owner
There4
Open source projects from Craig Davis and friends.
There4
Provides TemplateView and TwoStepView using PHP as the templating language, with support for partials, sections, and helpers.

Aura View This package provides an implementation of the TemplateView and TwoStepView patterns using PHP itself as the templating language. It support

Aura for PHP 83 Jan 3, 2023
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.

Slim Framework Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. Installation It's recommended

Slim Framework 11.5k Jan 4, 2023
Slim Framework - Prerequisite Checker

Slim Framework - Server Configuration Checker Upload the file check.php to your webserver Browse to the file: https://example.com/check.php Check the

Daniel Opitz 6 Aug 30, 2022
REST APIs using Slim framework. Implemented all CRUD operations on the MySql database

PHP REST API using slim framework and CRUD operations ?? Hi there, this is a simple REST API built using the Slim framework. And this is for the folks

Hanoak 2 Jun 1, 2022
A Slim PHP MVC framework built just for fun!

Aura Framework A Slim PHP MVC framework built just for fun! en: Note: This repository only contains the core code of the Aura framework. If you want t

Murilo Magalhães Barreto 2 Dec 16, 2021
Slim Framework skeleton application with MVC Schema

Slim Framework skeleton application with MVC Schema

JingwenTian 9 Apr 29, 2021
This repository contains a library of optional middleware for your Slim Framework application

Slim Framework Middleware This repository contains a library of optional middleware for your Slim Framework application. How to Install Update your co

Slim Framework 47 Nov 7, 2022
A curated list of awesome tutorials and other resources for the Slim micro framework

Awesome Slim A curated list of awesome tutorials and other resources for the Slim micro framework Table of Contents Essentials Tutorials Packages and

Sawyer Charles 466 Dec 8, 2022
Slim Framework 3 Skeleton Application + PagSeguro Lib

Slim Framework 3 Skeleton Application + PagSeguro Lib Aplicação simples para geração do Token para pagamentos no PagSeguro (método transparente) e env

Raí Siqueira 1 Feb 26, 2018
My personal blog developed on the Slim Framework

nesbot.com I am making the source code of my personal site available publicly in case it helps anybody. It's developed using the Slim Framework. I am

Brian Nesbitt 56 Sep 14, 2022
Juliangut Slim Framework Doctrine handler middleware

Juliangut Slim Framework Doctrine handler middleware Doctrine handler middleware for Slim Framework. Slim3 version Doctrine integration service for Sl

Julián Gutiérrez 6 Mar 23, 2021
This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library

This Slim Framework middleware will compile LESS CSS files on-the-fly using the Assetic library. It supports minification and caching, also via Asseti

Gerard Sychay 22 Mar 31, 2020
Strict PSR-7 implementation used by the Slim Framework

Strict PSR-7 implementation used by the Slim Framework, but you may use it separately with any framework compatible with the PSR-7 standard.

Slim Framework 96 Nov 14, 2022
Slim Framework custom views

Slim Views This repository contains custom View classes for the template frameworks listed below. You can use any of these custom View classes by eith

Slim Framework 302 Feb 21, 2022
Access control middleware for Slim framework

Slim Access Access control middleware for Slim framework. Supported formats IPv4 and IPv6 addresses CIDR notation all keyword Installation composer re

Alexandre Bouvier 7 Oct 22, 2019
Redis cache middleware for Slim framework

RedisCache Redis cache middleware for Slim framework. Installation composer require abouvier/slim-redis-cache Usage Cache every successful HTTP respo

Alexandre Bouvier 16 Sep 20, 2021
Slim Framework using Jade for templates

Welcome to Slim-Jade What? This is a boilerplate. It's the Slim Framework with jade.php to render views Why? I like the Sinatra style MVC and love Jad

Joe Fleming 23 Oct 16, 2019
The Slim PHP micro framework paired with Laravel's Illuminate Database toolkit.

Slim & Eloquent The Slim PHP micro framework paired with Laravel's Illuminate Database toolkit. Getting started # Download composer curl -s https://ge

Kyle Ladd 111 Jul 23, 2022
A set of shady Slim Framework middlewares that can solve some annoyances...

Shady A set of shady Slim Framework middlewares that can solve some annoyances... What does it contain? Available middlewares: ApacheVirtualHostFix Ur

Jan-Age Laroo 7 Jun 22, 2021