Search code examples
phpunitzend-framework3zend-testcontroller-tests

How to manipulate the application configs for controller tests?


I'm writing functional / controller tests for a ZF3 application (driven by PHPUnit and zendframework/zend-test). Like this:

public function testWhatEver()
{
    $this->dispatch('/');
    $this->assertResponseStatusCode(Response::STATUS_CODE_200);
}

It's working pretty well. But now I got a case, where I need to test the application with multiple mutually exclusive configs.

E.g., the case "authentication": The application provides multiple authentication methods (let's say: AuthA, AuthB,AuthC). (That is configurable via setting of the auth.type's value in the config file.) I want to test each of them. That means, it's not enough to have special test configs in the /config/autoload/test/*{local|global}.php. I need to be able to manipulate them for every test (before I call the dispatch(...) method).

How to manipulate the application configs for / from controller tests (on the fly)?


If no better solution can be found, a possible workaround might be to edit the config file (by using file_put_contents(...) or something like this) before every test. But it's a bit ugly (and slow).


Solution

  • In general I see no really nice solution for this problem. But there some more or less acceptable workaround:

    Workaround 1: manipulating the according config file for every test

    1. $configs = file_get_contents(...)
    2. searchByRegexAndManipulateConfigs(...)
    3. file_put_contents(...)

    It's much effort and would make the testing slower (due to reading from / writing to the filesystem).

    Workaround 2: simple files with only one config value

    We can create files like config.auth.type.php or config.auth.type.txt (one per config value t keep the file really simple) and to use inclue or file_get_contents(...) call as value in the config. The the value in the file needs to be manipulated before the test execution.

    It's a bit less effort (we don't need to write complex RegEx), but might make the test considerably slower, since every application request would start by reading an additional file.

    Workaround 3: passing configs values through GLOBALS

    It's the simplest and fastest variant. We just save the needed value into a global variable and read it in the config (file's) array. After the test we remove the variable:

    AuthBTest

    ...
    protected function setUp() // or setUpBeforeClass()
    {
        parent::setUp();
        $GLOBALS['appTestConfigs']['auth.type'] = 'AuthA';
    }
    
    protected function tearDown() // or tearDownAfterClass()
    {
        parent::tearDown();
        unset($GLOBALS['appTestConfigs']);
    }
    ...
    

    /config/autoload/test/local.php

    return [
        'auth' => [
            'type' => isset($GLOBALS['appTestConfigs']['auth.type']) ? $GLOBALS['appTestConfigs']['auth.type'] : 'AuthA',
        ],
    ];