Why I receive "CSRF token mismatch" while running tests in laravel? - laravel

I want to run my tests without receiving "CSRF token mismatch" exceptions. In the laravel documentation is noted that:
The CSRF middleware is automatically disabled when running tests.
the line of code where the exception is thrown looks like this:
$response = $this->json('POST', route('order.create'), [
'product_id', $product->id
]);
and for running tests I am working in my zsh terminal:
php artisan test --env=testing
This is my test class:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
class SessionCartTest extends TestCase
{
public function testExample()
{
$product = \App\Product::inRandomOrder()->first();
$response = $this->postJson(route('order.insert'), [
'product_id' => $product->id,
]);
$response->assertStatus(200); // here I receive 419
}
}
What am I doing wrong and how could I fix this? I am using laravel 7.

I ran into this problem x times now and each time I fix it by running:
php artisan config:clear

Probably the APP_ENV is not being set to testing.
You can set a ENV variable in the command line by preceding the php command.
So on your case set the environment to testing and run the artisan command by:
APP_ENV=testing php artisan test

Your data array is wrong. Try the following change:
$response = $this->postJson(route('order.insert'), [
'product_id' => $product->id, // use the arrow notation here.
]);

When you are running tests on Docker where the APP_ENV is hard coded with other values than testing (dev, local) in docker-compose.yaml file, phpunit cannot execute tests properly.
You will need to delete the all APP_ENV in docker files.

This works by setting a custom csrf-token
$this
->withSession(['_token' => 'bzz'])
->postJson('/url', ['_token' => 'bzz', 'other' => 'data']);

Related

Testing Laravel Cached Routes

I ran into an issue where Laravel's cached routes were not the same as uncached, so I am attempting to write a unit test which compares the two.
/** #test */
public function cached_and_uncached_are_identical()
{
Artisan::call('route:clear');
Artisan::call('route:list', ['--compact' => true]);
$uncached = Artisan::output();
Artisan::call('route:cache');
Artisan::call('route:list', ['--compact' => true]);
$cached = Artisan::output();
$this->assertSame($cached, $uncached);
}
The call to route:list after route:cache throws a LogicException: "Route is not bound."
I don't get that error when executing those commands on the command line. My searches haven't turned up any good hints for tracking down the issue.
How do I find the issue and fix it?

Laravel telegram bot sdk

I have test command and I want to call or sent request this command inside my controller, pls help me!
You can call the PHP artisan command inside your controller using the following way.
use Illuminate\Support\Facades\Artisan;
$project = TelegramBaza::select('name')->where('chat_id', $chatId)->first();
if($project && $project->name == 'ANORHOME'){
//Call artisan command
$exitCode = Artisan::call('message:send', [
'user' => $user, '--queue' => 'default'
]);
}
Documentation

Laravel Lumen function env() returns null sometimes

I am developing api with Lumen 6.2.0 which gets GET request with certain parameters and token. When it gets parameters it process it in a certain way and then encode with a secret key which is in my .env file and then compares result with the token which was provided with the request, if comparison result is true then user is authenticated else he is not. So the problem is sometimes env() function returns null. It doesn't happen pretty often, just like 1 request out of 15, but it's still a serious problem for me.
I googled a lot but found just few approaches. Firstly I found out that env() function should be only invoked in config file and since Lumen doesn't have a config directory and config files I have created it, but the issue remains the same. The second advice was for Laravel specifically - php artisan config:clear and php artisan config:cache but Lumen doesn't have such commands, although I ran the php artisan cache:clear command to no avail. So here is my code:
.env file
APP_NAME=Example
APP_ENV=local
APP_KEY=ApPkEyHeRe
APP_DEBUG=true
APP_URL=https://example.com
APP_TIMEZONE=UTC
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=dbname
DB_USERNAME=dbuser
DB_PASSWORD=dbpass
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
VK_APP_SECRET=SoMeFaNcYkEy
config/config.php
<?php
return [
'vk_app_secret' => env('VK_APP_SECRET'),
'events_per_page' => 16
];
And UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class UsersController extends Controller
{
public function check(Request $request) {
$query_params = $request->all();
$sign_params = [];
foreach ($query_params as $name => $value) {
if (strpos($name, 'vk_') !== 0) {
continue;
}
$sign_params[$name] = $value;
}
ksort($sign_params);
$sign_params_query = http_build_query($sign_params);
$secret = config('config.vk_app_secret');
$hash_hmac = hash_hmac('sha256', $sign_params_query, $secret, true);
$base_encode = base64_encode($hash_hmac);
$trim_chars = strtr($base_encode, '+/', '-_');
$sign = rtrim($trim_chars, '=');
$status = $sign === $query_params['sign'];
return json_encode($status);
}
}
I also logged every line of this algorithm, and noticed an interesting thing, the failing case contains [date] production.INFO: prefix before log's rows, and every successful case [date] local.INFO: So maybe it's affecting env() function somehow? I also don't get it why it sometimes logged as production when I have APP_ENV=local

Laravel 5.5 Queues & Jobs : job is never executed

I'm fairly new to Lumen (Laravel), and I'm currently digging the concept of Queues, Jobs & Scheduled Tasks.
I would like to store in a Queue some Eloquent models, when I receive them from API calls. Then, I want to create a scheduled task which runs a daily Job, to fetch all those models in Queue and then send a report email.
I went the database storing way for Queues.
So I added the QUEUE_DRIVER=database key in my .env file and my queue.php config file looks like this :
<?php
return [
'database' => [
'connection' => 'my_db_connection',
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90
]
];
I ran the php artisan queue:table command to create the migration file and ran migration to create my table. I have a table jobs, with the right intended fields.
I created a class, implementing ShouldQueue :
class ProcessDeliveryOrders implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $deliveryOrder;
public function __construct($deliveryOrder)
{
$this->deliveryOrder = $deliveryOrder;
}
public function handle()
{
// $this->deliveryOrder->save(); ?
}
}
As sub-question here is about how this class is working : Can it stores automatically the Eloquent model when it receives it in it's constructor ? to me the handle method is called when the object is retrieved by the Job, but I can be wrong and it's used to store the object ?
Then, I created a MailingJob : it's goal is to aggregate all the ProcessDeliveryOrders stored daily, and create an email from them :
class SendDeliveryEmailJob extends Job
{
public function __construct()
{
//
}
public function handle()
{
// DeliveryOrder is my Eloquent Model
$deliveryOrders = DeliveryOrder::query()
->whereBetween('createdAt', [strtotime('today midnight'), strtotime('today midnight')])
->get();
$mail = Mail::to(config('admin.emails'));
$mail->send(
new DeliveryOrderReportMailTemplate([
'deliveryOrders' => $deliveryOrders
])
);
}
}
And in my Kernel.php, I have added the following line in function schedule() :
// everyMinute for test purposes only
$schedule->job(new SendDeliveryEmailJob())->everyMinute();
As I'm using Lumen, I don't have the exact same process as in pure Laravel, so when I receive a delivery order to call my dispatch, I tried both ways exposed by the Lumen doc (forced to create an instance of my Job) :
dispatch(new ProcessDeliveryOrders($deliveryOrder));
// OR
Queue::push(new ProcessDeliveryOrders($deliveryOrder));
After all this setup, I tried few commands like php artisan queue:listen or php artisan queue:work, and the command line seems to be stuck.
If I run php artisan queue:listen database I get the following looped error :
In QueueManager.php line 172:
No connector for []
I checked documentation twice, and tried the new key QUEUE_CONNECTION=database instead of QUEUE_DRIVER but it's apparently only since 5.7, and didn't worked either. Any chance you spot something I'm missing ? Thanks a lot
EDIT: When I put a logging in the SendDeliveryEmailJob constructor, and I run php artisan queue:listen, I see the echo output every 2 or 3 seconds. I've also put a log into the handle function but I never see this one called.
EDIT 2: I noticed that when I try to execute my scheduled tasks with php artisan scheduled:run, it throws an error :
Running scheduled command: App\Jobs\SendDeliveryEmailJob
In Schedule.php line 87:
Call to a member function onQueue() on null
I guess from this message, that my Job is not instanciated, but I see the constructor message displayed to it's kinda weird..
#alex QUEUE_CONNECTION=database put this in your env and your queue.php is
'sync' => [
'driver' => 'sync',
],
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],

Doctrine\DBAL\Driver\PDOException: could not find driver when trying to use a factory in my unit tests

My unit tests work fine as long as I do not try to mock a DB object. I created a Factory and am trying to use it in one of my tests. However, I keep getting a could not find driver error. I have looked up a couple of stack answers and my version of php is 7.1, so not really sure what is causing the error.
Here is my testing class.
<?php
/**
* Created by PhpStorm.
*/
namespace Tests\Unit\Helper\Results;
use Jobscan\Helper\Results\FormatHelper;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Jobscan\Models\Document\Cv;
use Tests\TestCase;
class FormatHelperTest extends TestCase
{
public function testFindingsForUploadedDocxResume_whenFontTypeIsNotStandard_resultFontTypeShowsNegativeResult()
{
$cv = factory(Cv::class)->create([
'content' => "Testing Test test",
]);
dd($cv);
}
}
In my phpunit test
<env name="DB_CONNECTION" value="test_db"/>
<env name="DB_DATABASE" value=":memory:"/>
This is the error I keep getting
Caused by
Doctrine\DBAL\Driver\PDOException: could not find driver
database.php file
// This database is ephemeral and used for testing purposes.
'test_db' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
],
Define a setUp method in your test:
public function setUp()
{
parent::setUp();
}
Your error means it doesn't find the sqlite driver within your PHP lib which means the extension is not properly loaded.
Look into your php.ini file (find its path by doing : php --ini) and find :
extension=pdo_sqlite
If this is written as :
;extension=pdo_sqlite, then you should remove the ;.

Resources