5

I am using laravel 4 and created a class under its own namespace. Within this class there's a method that retrieves data and caches it. I also wrote a very small unit test to check if caching works. For some reason, caching does not work when unit testing, but does work when accessing through browser. I even modified app/config/testing/cache.php driver to use apc instead of array and it still doesn't work.

Here's the code:

<?php namespace site;
use Cache;

class UserController {
    public function testCaching( )
    {
        Cache::put('test', 'testing', 1);
        if (Cache::has('test')) die("YES: " . Cache::get('test')); die("NO");
    }

}

The routes.php file (works through browser, result: 'YES testing'):

Route::get('test-caching', 'site\UserController@register');

The test (does not work with phpunit, result: 'NO'):

<?php namespace site;
use Illuminate\Foundation\Testing\TestCase;
class SiteTest extends TestCase {
    /** @test */
    public function it_caches_vendor_token()
    {   
        $user = new UserController();
        $user->testCaching();
    }
}

Did anyone else experience this problem? Any solutions?

Problem Solver
  • 385
  • 1
  • 4
  • 11

1 Answers1

2

In unit testing, I would get Cache not found in ...

The problem was that I wasn't bootstraping correctly my test environment. Since my application wasn't correctly bootstrapped, it would not register the alias (Cache, Eloquent, Log, etc). To correctly bootstrap, you need to extend the TestCase provided that looks like

use Illuminate\Foundation\Testing\TestCase as BaseCase;

class TestCase extends BaseCase
{
    /**
     * The base URL to use while testing the application.
     *
     * @var string
     */
     protected $baseUrl = 'http://localhost.dev';

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

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

         return $app;
     }
}

and in your test should look like this

class MyBrandNewTest extends TestCase 
{
    // You can omit to override this method if you
    // do not have custom setup logic for your test case
    public function setUp()
    {
        parent::setUp();

        // Do custom setup logic here
    }
}

parent::setUp() will call the setUp method in BaseTest which will bootstrap the test environment.

Lunfel
  • 2,499
  • 21
  • 29
  • Why are you overriding the parent `setUp` with a call to the parent method? – Christian Oct 08 '20 at 09:50
  • I did this, because I oftenly use the setUp in my test cases to generate data. But in here since it's empty it does not make sense. I will edit to make that more clear. So, if you don't need to do stuff at setUp, dont put the method at all. But if you do, you should override the method, call the parent method and then do your own custom logic. – Lunfel Oct 08 '20 at 17:05
  • 1
    Ok, please do. I've seen a lot of people needlessly overriding it (maybe they just leave autogenerated code) and it's become a bit of a pet peeve. – Christian Oct 08 '20 at 17:42