Testing Your Application
This chapter describes how to test your application against your reverse proxy. By running your tests against a live instance of your proxy server, you can validate the caching headers that your application sets, and the invalidation rules that it defines.
The FOSHttpCache library provides traits and base test classes to help you write functional tests with PHPUnit 5.7 and 6.*. Using the traits, you can extend your own (or your framework’s) base test classes. For convenience, you can also extend the FOSHttpCache base test class suitable for your proxy server, which includes a sensible set of traits.
By using the traits, you get:
independent tests: all previously cached content is removed in the test’s
setUp()
method;an instance of this library’s proxy client that is configured to talk to your proxy server for invalidation requests;
a convenience method for executing HTTP requests to your proxy server:
$this->getResponse()
;custom assertions
assertHit()
andassertMiss()
for validating a cache hit/miss.
Configuration
The recommended way to configure the test case is by setting constants
in your phpunit.xml
. Alternatively, you can override the getter methods.
Web Server
You will need to run a web server to provide the PHP application you want to
test. The test cases only handle running the proxy server. It’s easiest to
use PHP’s built in web server. Include the WebServerSubscriber in your
phpunit.xml
, either using the extension provided by this package or your own:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<extensions>
<bootstrap class="FOS\HttpCache\Test\WebServerSubscriberExtension"/>
</extensions>
</phpunit>
Then set the webserver
group on your test to start PHP’s web server before
it runs:
use PHPUnit\Framework\Attributes as PHPUnit;
class YourTest extends \PHPUnit_Framework_TestCase
{
#[PHPUnit\Group('webserver')]
public function testYourApp()
{
// The web server will be started before this test code runs and
// shut down again after it finishes.
}
}
Setting Constants
Compare this library’s configuration to see how the constants are set:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
<php>
<const name="NGINX_FILE" value="./tests/Functional/Fixtures/nginx/fos.conf"/>
<const name="WEB_SERVER_HOSTNAME" value="localhost"/>
<const name="WEB_SERVER_PORT" value="8080"/>
<const name="WEB_SERVER_DOCROOT" value="./tests/Functional/Fixtures/web"/>
</php>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit>
Overriding Getters
You can override getters in your test class in the following way:
use FOS\HttpCache\Test\VarnishTestCase;
class YourFunctionalTest extends VarnishTestCase
{
protected function getVarnishPort()
{
return 8000;
}
}
Traits
Proxy Server Traits
FOSHttpCache provides three proxy server traits that:
if necessary, start your proxy server before running the tests;
clear any cached content between tests to guarantee test isolation;
if necessary, stop the proxy server after the tests have finished;
provide
getProxyClient()
, which returns the right proxy client for your proxy server.
You only need to include one of these traits in your test classes. Which one
you need (VarnishTest
, NginxTest
or SymfonyTest
) depends on the
proxy server that you use.
VarnishTest Trait
Requires Symfony’s Process component, so make sure to include that in your project:
$ composer require symfony/process
Then configure the following parameters. The web server hostname and path to your VCL file are required.
Then set your Varnish configuration (VCL) file. Configuration is handled either
by overwriting the getter or by defining a PHP constant. You can set the
constants in your phpunit.xml
or in the bootstrap file. Available
configuration parameters are:
Constant |
Getter |
Default |
Description |
---|---|---|---|
|
|
hostname your application can be reached at |
|
|
|
your Varnish configuration (VCL) file |
|
|
|
|
your Varnish binary |
|
|
|
port Varnish listens on |
|
|
|
Varnish management port |
|
|
|
directory to use for cache |
|
|
hostname your application can be reached at |
The Varnish version is controlled by an environment variable (in case you want
to test both Varnish 3 and 4 on a continuous integration system). See the
.travis.yml
of the FOSHttpCache git repository for an example.
Environment Variable |
Getter |
Default |
Description |
---|---|---|---|
|
|
|
version of Varnish application that is used |
See tests/bootstrap.php
for an example how this repository uses the version
information to set the right VARNISH_FILE
constant.
Enable Assertions
For the assertHit and assertMiss assertions to work, you need to add a custom X-Cache header to responses served by your Varnish.
NginxTest Trait
Requires Symfony’s Process component, so make sure to include that in your project:
$ composer require symfony/process
Then configure the following parameters. The web server hostname and path to your NGINX configuration file are required.
Constant |
Getter |
Default |
Description |
---|---|---|---|
|
|
hostname your application can be reached at |
|
|
|
your NGINX configuration file |
|
|
|
|
your NGINX binary |
|
|
|
port NGINX listens on |
|
|
|
directory to use for cache Must match proxy_cache_path directive in your configuration file. |
SymfonyTest Trait
It is assumed that the web server you run for the application has the HttpCache integrated.
Constant |
Getter |
Default |
Description |
---|---|---|---|
|
|
Hostname your application can be reached at |
|
|
|
The port on which the web server runs |
|
|
|
|
directory to use for cache Must match the configuration of your HttpCache and must be writable by the user running PHPUnit. |
HttpCaller Trait
Provides your tests with a getResponse
method, which retrieves a URI from
your application through a real HTTP call that goes through the HTTP proxy server:
use FOS\HttpCache\Test\HttpCaller;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
use HttpCaller;
public function testCachingHeaders()
{
// Get some response from your application
$response = $this->getResponse('/path');
// Optionally with request headers and a custom method
$response = $this->getResponse('/path', ['Accept' => 'text/json'], 'PUT');
}
}
This trait requires the methods getHostName()
and getCachingProxyPort()
to exist. When using one of the proxy server traits, these will be provided by
the trait, otherwise you have to implement them.
CacheAssertions Trait
Provides cache hit/miss assertions to your tests. To enable the these
assertHit
and assertMiss
assertions, you need to configure your proxy
server to set an X-Cache
header with the cache status:
Then use the assertions as follows:
use FOS\HttpCache\Test\CacheAssertions;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
public function testCacheHitOrMiss()
{
// Assert the application response is a cache miss
$this->assertMiss($response);
// Or assert it is a hit
$this->assertHit($response);
}
}
Base Classes for Convenience
If you prefer, you can extend your test classes from VarnishTestCase
,
NginxTestCase
or SymfonyTestCase
. The appropriate traits will then
automatically be included.
Usage
This example shows how you can test whether the caching headers your application sets influence your proxy server as you expect them to:
use FOS\HttpCache\Test\CacheAssertions;
use FOS\HttpCache\Test\HttpCaller;
use FOS\HttpCache\Test\VarnishTest;
// or FOS\HttpCache\Test\NginxTest;
// or FOS\HttpCache\Test\SymfonyTest;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
public function testCachingHeaders()
{
// The proxy server is (re)started, so you don’t have to worry
// about previously cached content. Before continuing, the
// VarnishTest/ NginxTest trait waits for the proxy server to
// become available.
// Retrieve a URL from your application
$response = $this->getResponse('/your/resource');
// Assert the response was a cache miss (came from the backend
// application)
$this->assertMiss($response);
// Assume the URL /your/resource sets caching headers. If we
// retrieve it again, we should have a cache hit (response delivered
// by the proxy server):
$response = $this->getResponse('/your/resource');
$this->assertHit($response);
}
}
This example shows how you can test whether your application purges content correctly:
use FOS\HttpCache\Test\CacheAssertions;
use FOS\HttpCache\Test\HttpCaller;
use FOS\HttpCache\Test\VarnishTest;
// or FOS\HttpCache\Test\NginxTest;
// or FOS\HttpCache\Test\SymfonyTest;
use PHPUnit\Framework\TestCase;
class YourTest extends TestCase
{
public function testCachePurge()
{
// Again, the proxy server is restarted, so your test is independent
// from other tests
$url = '/blog/articles/1';
// First request must be a cache miss
$this->assertMiss($this->getResponse($url));
// Next requests must be a hit
$this->assertHit($this->getResponse($url));
// Purge
$this->getProxyClient()->purge('/blog/articles/1');
// First request after must again be a miss
$this->assertMiss($this->getResponse($url));
}
}
For more ideas, see this library’s functional tests in the
tests/Functional/
directory.