However, I haven’t found a great deal of information about integration and unit testing with Slim, and have developed an approach that allows complete end-to-end testing of an application. You can use this testing a REST framework, or a complete website. In particular, I think it’s a great way to handle regression testing. I’m presenting a sample application that I hope will help others on their path to using this great framework.
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.
The core idea of this approach is that we isolate our application routes into their own file. This allows us to include this route file into both a production context via an index.php file, and also include it within a unit testing bootstrap harness in our testing context. The unit testing context with use the internal
Slim\Environment::mock() method to setup an environment for our application.
Here’s what the app looks like:
public/index.php file serves as the application entry point. This file initializes a SlimPHP
$app with production configuration, includes the routes file from
app/app.php and then runs the app with
$app->run();. This allows us to keep our application separate from the index, and gives us an opportunity to include our
app/app.php file in a different context.
When phpunit runs, it looks for the phpunit.xml file in our root. This file specifies a testing bootstrap file. PHPUnit includes
testing/bootstrap.php. This file creates an
$app, just like in
index/index.php, but it uses testing configuration. The bootstrap keeps a reference to
$app for the testing framework, and then provides several helper methods for
With these methods, you can run end to end tests on SlimPHP routes without a webserver. The tests run entirely within a mock environment, and will be fast and efficient.
Unit Testing vs. Integration Testing
Unit tests should test an individual part of code. The system under test should be as small as possible. You would unit test an individual method. Integration testing exercises an entire system. Most of this example is about integration testing. We are running tests that work Slim from initial instantiation to the final delivery of data. With integration tests, we’re treating the entire application as a unit, setting up a particular initial environment and then executing the
run() command and finally inspecting the results to ensure that they match our expectations.
Mocking with SlimPHP
See the ZenTest for an example of mocking with SlimPHP dependency injection. In this test we mock a Curl wrapper class from Shuber. This allows us to substitute responses and exercise the parts of our application that we feel need testing. It also allows us to run these unit tests on systems that don’t have the curl extension installed. We’re totally isolated from that dependency while this running test.
The FileStoreTest uses a mock for the authentication class. Notice that the file store route doesn’t use that class directly, but instead it is used by the application authenticator method. We’re using the app dependency injection container to swap out the real object for a mock version. This approach allows us to control authentication results from within our test harness.