Laravel 5.6 testing Notification::assertSentTo() not found - laravel

Struggling since multiple days to get Notification::assertSentTo() method working in my feature test of reset password emails in a Laravel 5.6 app, yet receiving ongoing failures with following code:
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserPasswordResetTest extends TestCase
{
public function test_submit_password_reset_request()
{
$user = factory("App\User")->create();
$this->followingRedirects()
->from(route('password.request'))
->post(route('password.email'), [ "email" => $user->email ]);
Notification::assertSentTo($user, ResetPassword::class);
}
}
I have tried several ideas including to use Illuminate\Support\Testing\Fakes\NotificationFake directly in the use list.
In any attempt the tests keep failing with
Error: Call to undefined method Illuminate\Notifications\Channels\MailChannel::assertSentTo()
Looking forward to any hints helping towards a succesful test.
Regards & take care!

It seems like you are missing a Notification::fake(); For the correct fake notification driver to be used.
Notification::fake();
$this->followingRedirects()
...

Related

When to use HTTP Request and when to use Illuminate Support Facades Request in laravel?

I have been using laravel so far but sometimes I am so confused about choosing correct Request listed bellow.
use Request;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Request;
I have created a test method to my corresponding Route & Controller like bellow.
public function test()
{
dd(Request::all());
}
If I choose use Illuminate\Support\Facades\Request; or use Request; it work's fine and get empty array.
But When I choose use Illuminate\Http\Request;
I get error message saying Request::all() should not be called statically. So, it arises two question in my mind.
What's the difference among them ?
When to use Http Request or Illuminate Support Facades Request. Thanks
public function test(Request $request)
{
dd($request->all());
}
Try This

How to test a route in Laravel that uses both `Storage::put()` and `Storage::temporaryUrl()`?

I have a route in Laravel 7 that saves a file to a S3 disk and returns a temporary URL to it. Simplified the code looks like this:
Storage::disk('s3')->put('image.jpg', $file);
return Storage::disk('s3')->temporaryUrl('image.jpg');
I want to write a test for that route. This is normally straightforward with Laravel. I mock the storage with Storage::fake('s3') and assert the file creation with Storage::disk('s3')->assertExists('image.jpg').
The fake storage does not support Storage::temporaryUrl(). If trying to use that method it throws the following error:
This driver does not support creating temporary URLs.
A common work-a-round is to use Laravel's low level mocking API like this:
Storage::shouldReceive('temporaryUrl')
->once()
->andReturn('http://examples.com/a-temporary-url');
This solution is recommended in a LaraCasts thread and a GitHub issue about that limitation of Storage::fake().
Is there any way I can combine that two approaches to test a route that does both?
I would like to avoid reimplementing Storage::fake(). Also, I would like to avoid adding a check into the production code to not call Storage::temporaryUrl() if the environment is testing. The latter one is another work-a-round proposed in the LaraCasts thread already mentioned above.
I had the same problem and came up with the following solution:
$fakeFilesystem = Storage::fake('somediskname');
$proxyMockedFakeFilesystem = Mockery::mock($fakeFilesystem);
$proxyMockedFakeFilesystem->shouldReceive('temporaryUrl')
->andReturn('http://some-signed-url.test');
Storage::set('somediskname', $proxyMockedFakeFilesystem);
Now Storage::disk('somediskname')->temporaryUrl('somefile.png', now()->addMinutes(20)) returns http://some-signed-url.test and I can actually store files in the temporary filesystem that Storage::fake() provides without any further changes.
Re #abenevaut answer above, and the problems experienced in the comments - the call to Storage::disk() also needs mocking - something like:
Storage::fake('s3');
Storage::shouldReceive('disk')
->andReturn(
new class()
{
public function temporaryUrl($path)
{
return 'https://mock-aws.com/' . $path;
}
}
);
$expectedUrl = Storage::disk('s3')->temporaryUrl(
'some-path',
now()->addMinutes(5)
);
$this->assertEquals('https://mock-aws.com/some-path', $expectedUrl);
You can follow this article https://laravel-news.com/testing-file-uploads-with-laravel, and mix it with your needs like follow; Mocks seem cumulative:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
public function testAvatarUpload()
{
$temporaryUrl = 'http://examples.com/a-temporary-url';
Storage::fake('avatars');
/*
* >>> Your Specific Asserts HERE
*/
Storage::shouldReceive('temporaryUrl')
->once()
->andReturn($temporaryUrl);
$response = $this->json('POST', '/avatar', [
'avatar' => UploadedFile::fake()->image('avatar.jpg')
]);
$this->assertContains($response, $temporaryUrl);
// Assert the file was stored...
Storage::disk('avatars')->assertExists('avatar.jpg');
// Assert a file does not exist...
Storage::disk('avatars')->assertMissing('missing.jpg');
}
}
Another exemple for console feature tests:
command : https://github.com/abenevaut/pokemon-friends.com/blob/1.1.3/app/Console/Commands/PushFileToAwsCommand.php
test : https://github.com/abenevaut/pokemon-friends.com/blob/1.1.6/tests/Feature/Console/Files/PushFileToCloudCommandTest.php

How can run Binance api in laravel with Controller

I can't use binance api in laravel
I installed Php binance api from composer require "jaggedsoft/php-binance-api #dev" but examples not working in laravel.I had some errors when I tried.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
require '../vendor/autoload.php';
class BinanceController extends Controller
{
public function list()
{
$api = new Binance\API();
$key = "----";
$secret = "---";
$api = new Binance\API($key, $secret);
$price = $api->price("BNBBTC");
return $price;
}
}
When I runned the route I got this error:
Symfony\Component\Debug\Exception\FatalThrowableError Class
'App\Http\Controllers\Binance\API' not found
You're not importing Binance\API correctly. Laravel believes the Binance\Api class is located in the App\Http\Controllers\Binance namespace. Which it is not.
Try $api = new \Binance\API();
Or put it in your use cases.
use Binance\API
I also found an old wrapper which you may be able to import if there hasn't been any changes to Binance since but I highly doubt it. Since your case is specific to Laravel, look for a Binance wrapper for Laravel specifically. Here may contain some useful information on how to use non-laravel packages, with laravel

Class 'Illuminate\Support\Facade\Mail' not found in laravel 5

I get this error message while trying to send email (Class 'Illuminate\Support\Facade\Mail' not found).
in the controller, I have included 'use Illuminate\Support\Facade\Mail;' in the begining of the controller class (PostsController) and in the store function (of the controller), I have this
Mail::send('welcome_email', $data, function ($message) {
$message->from('walegbenga807#gmail.com', 'Coa Blog');
$message->to('nigeriawonderboy#gmail.com')->subject('There is a new post!');
});
return redirect('/')->with('status', 'ticket created');
Try to change the
use Illuminate\Support\Facade\Mail
to
use Illuminate\Support\Facades\Mail;
Since it's a facade, just add this to the top of the class:
use Mail;
Or use full namespace when using the facade:
\Mail::send
Try to use 'use Illuminate\Support\Facades\Mail';
Actually there is no Facade package, but Facades.
Laravel don't know what is "Facade" but try adding s for Facade word.
Try to use
use Illuminate\Support\Facades\Mail;
For more about facades refer:
Facades

Accessing Model in utility in laravel

I'm trying to access the User model in a utility I built that will eventually send emails out, this is being triggered with by cron, and I'm using php artisan schedule:run to test it. Below is the utility I'm starting to build out, and currently when test it I am getting 'I was triggered'. This is being triggered by a registered console command. Thats all working.
<?php
namespace App\Utility;
use Log;
use Mail;
use App\User;
class ReferralProgramUtility
{
static public function test()
{
LOG::info("I was triggered");
}
}
However, when I change this to pull in the User model....
<?php
namespace App\Utility;
use Log;
use Mail;
use App\User;
class ReferralProgramUtility
{
static public function test()
{
$user = User::all();
LOG::info($user);
}
}
I get the following error....
Trying to get property of non-object in /var/www/html/appname/app/User.php:32
I'm using another utility that has a similar configuration and uses the User model and this work fine, the only difference is that this is on is being triggered by task scheduler. Not sure what is causing this, and I'm fairly new to Laravel so any tips or recommendation would be hugely appreciated. Thanks, in advance.

Resources