Framework: Unit test fails if config is cached

Created on 29 Apr 2016  路  9Comments  路  Source: laravel/framework

I have written tests for application. there are plenty of test files. but when i cache the config by running command "php artisan config:cache", some of tests fail (like email sending tests and some db transactions related tests).
when I clear config cache, all tests pass without any problem.

Why it is so? why cached config affect unit testing result?

Most helpful comment

For anyone who wants an automated worry-free solution to this problem, merge this into to your tests/TestCase.php class:

    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

        $this->clearCache(); // NEW LINE -- Testing doesn't work properly with cached stuff.

        return $app;
    }

    /**
     * Clears Laravel Cache.
     */
    protected function clearCache()
    {
        $commands = ['clear-compiled', 'cache:clear', 'view:clear', 'config:clear', 'route:clear'];
        foreach ($commands as $command) {
            \Illuminate\Support\Facades\Artisan::call($command);
        }
    }

All 9 comments

Thanks but this is not a bug, just a limitation introduced in L5.2, which allowed us to increase request throughput by 25%.

You need to delete the cached config in order to have us load the test environment.

Note that config and route caching are intended for use when deploying to production. Don't use them on local dev, since they'll stop you running the tests with a testing environment.

Thanks for information. I guessed the same but just wanted to be sure.

No problem. :)

For anyone who wants an automated worry-free solution to this problem, merge this into to your tests/TestCase.php class:

    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

        $this->clearCache(); // NEW LINE -- Testing doesn't work properly with cached stuff.

        return $app;
    }

    /**
     * Clears Laravel Cache.
     */
    protected function clearCache()
    {
        $commands = ['clear-compiled', 'cache:clear', 'view:clear', 'config:clear', 'route:clear'];
        foreach ($commands as $command) {
            \Illuminate\Support\Facades\Artisan::call($command);
        }
    }

I feel @katzenbaer solution should be the default.
Although this is an opinion I feel most developers do not expect their test configuration to come from previously cached values.
I surely didn't expect it when I accidentaly whacked my own development database 馃槉

I've updated solution of @katzenbaer and now my development database won't get wiped out, when cache files exist.

     /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Kernel::class)->bootstrap();

        $this->clearCache(); // NEW LINE -- Testing doesn't work properly with cached stuff.

        // these are to refresh configs and environment variables, since $app has loaded cache before it was cleared
        $app->make(\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class)->bootstrap($app);
        $app->make(\Illuminate\Foundation\Bootstrap\LoadConfiguration::class)->bootstrap($app);

        return $app;
    }

I tried the suggestion @moff offered, but somehow the first testcase still had the old cache. I had to rebuild my entire application.

```
/**

  • Creates the application.
    *
  • @return \Illuminate\Foundation\Application
    */
    public function createApplication()
    {
    $createApp = function() {
    $app = require __DIR__.'/../bootstrap/app.php';
    $app->make(Kernel::class)->bootstrap();
    return $app;
    };
$app = $createApp();
if ($app->environment() !== 'testing') {
    $this->clearCache();
    $app = $createApp();
}

return $app;

}

Was this page helpful?
0 / 5 - 0 ratings