Reset Redis database after each test in laravel - laravel

In my laravel application, I use Redis to store some cache (e.g. the list of items to show on the front page). I always access Redis through the Facade: Illuminate\Support\Facades\Redis.
I created a different Redis database for testing (1 instead of 0), but I also need to reset it after each test, so that the test never gets data from a previous test.
Is there an efficient way to create this behaviour?
I tried to implement it using the #before annotation:
/**
* #before
*/
public function prepareForTesting() {
Redis::flushdb();
}
But I get the error: Cannot use 'FLUSHDB' over clusters of connections.
Any ideas?

Maybe you could use the built in artisan cache:clear command?
Like this:
/**
* #before
*/
public function prepareForTesting() {
Artisan::call('cache:clear');
}

Related

Check if input is from console

I want to share a variable of my views with:
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
\Schema::defaultStringLength(191);
$customers = Customer::get();
\View::share('customers', $customers);
}
}
it works as expected, but when I want to migrate my tables via artisan it throws an error, that the table for customers was not found because it is checked BEFORE the migration starts. So I need something like
if(!artisan_request) {
//request to laravel is via web and not artisan
}
But I haven't found anything in the documentation.
You can check if you are running in the console by using
app()->runningInConsole()
Underneath that, all it does is check the interface type
return php_sapi_name() == 'cli' || php_sapi_name() == 'phpdbg'
You can find more on the PHP Docs site
To detect whether the app is running in console, you can do something like this:
use Illuminate\Support\Facades\App;
if(App::runningInConsole())
{
// app is running in console
}
See, illuminate/Foundation/Application.php:520

Laravel DatabaseTransactions for PHPunit have no effect

Writing tests for an existing API, there are many cases where the database has been modified. What I have been doing is something as follows:
public function testPut()
{
//setup
/*Copy an existing record and take its data as an array.
* the function being tested will take an array of data
* and create a new record. Using existing data guarantees
* the data is valid.
*/
$customerObj = Customer::getInstance(); //regular instantiation disabled in this api
$cust = ArCust::first()->toArray();
$oldNum = $cust['CUST_NO'];
unset($cust['CUST_NO']);
$custNo = rand(1, 9999999999999);
//test
/*put() creates a new customer record in the database
and returns the object.
*/
$this->assertInternalType('object', $customerObj->put($custNo, $cust));
//cleanup
/*manually remove the newly created record.
*/
ArCust::whereNam($cust['NAM'])->whereNotIn('CUST_NO', [$oldNum])->delete();
}
I am now running into instances where the API creates or updates many tables based on foreign keys. It would take far too much time to go through and manually reset each table.
The DatabaseTransaction trait provided by Laravel is supposed to take care of resetting everything for you. However, when I use it, I still find the test-created records in the database.
Here is how I have used it:
class CustomerTest extends TestCase
{
use DatabaseTransactions;
public function testPut()
{
//setup
$customerObj = Customer::getInstance();
$cust = ArCust::first()->toArray();
$oldNum = $cust['CUST_NO'];
unset($cust['CUST_NO']);
$custNo = rand(1, 9999999999999);
//test
$this->assertInternalType('object', $customerObj->put($custNo, $cust));
}
}
Am I using this incorrectly? Getting DatabaseTransactions to work correctly will save an incredible amount of time, as well as make the testes more readable to other people.
The issue was that we had multiple database connections defined in config > database.
In the database.php conf file, I changed the default connection to the correct database using its name as defined in the setup:
$connection = 'counterpoint';
and DatabaseTransactions now works.
This next step to this solution is to direct the connection of each test to the appropriate database rather than change the global connection.

EventServiceProvider laravel 5

I am digging down the code of laravel 5 to understand it better. I started from index page and I am stuck at register part at the moment.
use Illuminate\Support\ServiceProvider;
class EventServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->app->singleton('events', function($app)
{
return (new Dispatcher($app))->setQueueResolver(function() use ($app)
{
**return $app->make('Illuminate\Contracts\Queue\Queue');**
});
});
}
}
I don't understand the part "$app->make('Illuminate\Contracts\Queue\Queue');". "Illuminate\Contracts\Queue\Queue" is interface not a class. It should throw an error message for this process. however i don't see any error message. I assume that it's not called at this time?
It would be appreciated if you can explain what's happening here.
Thanks in advance.
I spent a couple of minutes investigating the classes and came up with the following:
Please take a look at the https://github.com/illuminate/queue laravel/framework repository subtree split.
The interface Illuminate\Contracts\Queue\Queue is implemented by all queue types available by default:
BeanstalkdQueue
RedisQueue
SqsQueue
NullQueue
SyncQueue
DatabaseQueue
IronQueue
The Laravel IoC conatainer should resolve one of these when calling $app->make('Illuminate\Contracts\Queue\Queue') so I do not think that the application will fail, when executing this lines of code.
Unfortunately I could not find the location where a specific Queue implementation is set for the IoC container, I will update my answer as soon as I found out.

Laravel - setting up a test database

With my laravel application I have a bunch of migrations and db seed data.
In app/config/testing/database.php I have set a mysql database for testing.
I've populated the test database with migrate and db:seed commands, specifying the testing environment.
This works pretty well, but I want to call those commands each time I run phpunit. If it do it in the setUp then it takes so long as it's called on every single test.
I can also call it in the setUpBeforeClass which is better, but still longer if I am testing 10 classes.
Is there a way I can all it just once when I run phpunit ?
For now I have done this, in the tests/TestCase.php
class TestCase extends Illuminate\Foundation\Testing\TestCase {
public static $setupDatabase = true;
public function setUp()
{
parent::setUp();
if(self::$setupDatabase)
{
$this->setupDatabase();
}
}
public function setupDatabase()
{
Artisan::call('migrate');
Artisan::call('db:seed');
self::$setupDatabase = false;
}
....
which seems to work, but doesn't feel ideal, but means I can easily re-setup the db if I need to reset it for a test...

Doctrine 2 result cache invalidation

I'm using Doctrine 2's result cache on a query retrieving the number of new messages of a user (messaging app):
$query->useResultCache(true, 500, 'messaging.nb_new_messages.'.$userId);
I tried to invalidate this cache like this (in my entity repository):
public function clearNbNewMessagesOfUserCache($userId) {
$cacheDriver = $this->getEntityManager()->getConfiguration()->getResultCacheImpl();
$result = $cacheDriver->delete('skepin_messaging.nbNewMessages.'.$userId);
if (!$result) {
return false;
}
return $cacheDriver->flushAll();
}
So that I don't need to make a useless query on each page of my website.
My questions: is that a recommended practice? Will I eventually run into problems?
I had the idea to build an onFlush hook.
There you have all entities queued for inserts, updates and deletes hence you can invalidate the caches depending on entity name and identifier etc.
Unfortunately, I have not yet build any event listeners but I definitely plan to build such a thing for my project.
Here is a link to the doctrine documentation for the onFlush event
Edit:
There is even an easier way to implement events.
In an entity class you can add #HasLifecycleCallbacks to the annotations and than you can define a function with a #PreUpdate or #PrePersist annotation.
Than every time this model is updated or persisted this function will be called.
/**
* #Entity
* #Table(name="SomeEntity")
* #HasLifecycleCallbacks
*/
class SomeEntity
{
...
/**
* #PreUpdate
* #PrePersist
*/
public function preUpdate()
{
// This function is called every time this model gets updated
// or a new instance of this model gets persisted
// Somethink like this maybe...
// I have not yet completely thought through all this.
$cache->save(get_class($this) . '#' . $this->getId(), $this);
}
}
So maybe this can be used to invalidate every single instance of an entity?
This is an old question I stumbled upon. It's really simple using Doctrine 2.8 nowadays:
/** #var \Psr\Cache\CacheItemPoolInterface|null $cache */
$cache = $em->getConfiguration()->getResultCache();
$cache->deleteItem('skepin_messaging.nbNewMessages.'.$userId);
$cache->clear(); // clear all items
Please be aware that Doctrine internally generates a "real cache key" which won't look like yours. I don't know how to generate that cache key, without re-creating the used query.

Resources