sitilge
sitilge

Reputation: 3737

Proper require unit test

I have been writing a unit test for an app and wanted to test a method which has require. The way I see it

public $configPath = __DIR__.'/path/to/config.php';

private function getConfig()
{
    if (!empty($this->config)) {
        return $this->config;
    }

    return $this->config = require $this->configPath;
}

public method foo()
{
    $config = $this->getConfig(); 
    //logic here
}

In the test case, the respective snippet is

$class->config = ['bar' => 'baz'];

$class->foo();

I am wondering if this could be considered as the proper way or other technique/solution should be used?

Upvotes: 2

Views: 49

Answers (1)

Jakub Zalas
Jakub Zalas

Reputation: 36191

The require statement loads a file from the filesystem. Since it interacts with the infrastructure it should be integration tested rather than unit tested. However, there are ways of decoupling from the filesystem so you could properly unit test it.

Integration test

If you decided to write an integration test for your class, you could make the path to the configuration file configurable via a constructor argument. This way you'll be able to pass a "test" config file with values you can rely on in the test.

Unit test

If you decided to write a unit test you'd need to move file loading out of your class. Either pass result of loading the config file as a constructor argument, or delegate file loading to a collaborator (i.e. ConfigLoader). You'll be able to stub the ConfigLoader in your unit test. The implementation of ConfigLoader will be very simple and you'll write an integration test for it (just to see if file is loaded and array is returned).

For example:

class ConfigLoader
{
    public function load($file)
    {
        $config = require $file;

        if (!is_array($config)) {
            throw new InvalidConfigFileException(sprintf('Did not find configuration in "%s".', $file));
        }

        return $config;
    }
}

Which approach to choose?

It depends on what's the responsibility of the config class you're trying to test (remember of Single Responsibility Principle).

If the responsibility of the config class is related purely to loading a config file - integration test it. If there's something more to it - extract the file loading responsibility to its own class.

Upvotes: 1

Related Questions