Not able to test the sending of a notification in the RegisterController. Though the application is working just fine, I can't make the test asserting OK...
In my app, I modified the RegisterController so a new users gets a mail notification when he registers.
Here is my RegisterController's create function:
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return User
*/
protected function create(array $data)
{
$user = User::create(
[
'firstname' => $data['firstname'],
'lastname' => $data['lastname'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]
);
Notification::send($user, new UserSubscribed());
return $user;
}
Then, my notification class is
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class UserSubscribed extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Welcome')
->line('Welcome')
->line('Update your profile')
->action('some action link')
->line('Thank you');
}
}
The application works fine and everything is going well... But when I want to test it:
public function testUserCanRegister()
{
Notification::fake();
// Check email adress is unique in DB by deleting whoever would already have this email.
$email = '[email protected]';
$test = User::where(['email' => $email])->delete();
// Make a user
$user = factory(User::class)->make(['email' => '[email protected]']);
// Make Request
$response = $this->post('/register', [
'firstname' => $user->firstname,
'lastname' => $user->lastname,
'email' => $user->email,
'password' => 'testing',
]);
// Assert a notification was sent to the user
Notification::assertSentTo($user, UserSubscribed::class);
$response->assertStatus(302);
$response->assertRedirect('/');
// Tear Down
// Delete created user
User::where(['email' => $email])->delete();
}
Then I get the error message:
1) Tests\Feature\RegisterTest::testUserCanRegister
The expected [App\Notifications\UserSubscribed] notification was not sent.
Failed asserting that false is true.
/home/lucius/womyjob/wmj-code/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:39
/home/lucius/womyjob/wmj-code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:221
/home/lucius/womyjob/wmj-code/tests/Feature/RegisterTest.php:42
If you start with the test
public function testUserCanRegister()
{
// Check email adress is unique in DB by deleting whoever would already have this email.
$email = '[email protected]';
$test = User::where(['email' => $email])->delete();
// Make a user
$user = factory(User::class)->make(['email' => '[email protected]']);
// Make Request
$response = $this->post('/register', [
'firstname' => $user->firstname,
'lastname' => $user->lastname,
'email' => $user->email,
'password' => 'testing',
]);
$response->assertStatus(302);
$response->assertRedirect('/');
// Tear Down
// Delete created user
User::where(['email' => $email])->delete();
}
Then the test passes and the Notification is actually sent.
Next, add
Notification::fake()
The test still passes and the notification is no more sent. Which is good.
Finally, add the line
Notification::assertSentTo($user, UserSubscribed::class);
And I get the error...
If I replace by
Notification::assertNotSentTo($user, UserSubscribed::class);
Then the test passes again...
For info: I started my app in Laravel 5.2 about a year ago, then I migrated progressively to 5.4... I never had any other problems since now...
I don't think it's an issue with the core, please try to replicate in a fresh laravel installation.
The $user you are putting in your test is not the $user used in your register method - because in your register method you are creating a new $user
You need to do something like:
Notification::assertSentTo(User::latest()->first(), UserSubscribed::class);
to get the latest user from the DB table and use that. I havent tested the code - you get the general idea.
But it is not a bug in the framework - so this issue should be closed.
Thank you so much! It works now...
Thank you so much! It works now...
@LuciusCaesar
How did you solved this issue I have the issue but no luck with any solution ?
Thank you so much! It works now...
@LuciusCaesarHow did you solved this issue I have the issue but no luck with any solution ?
Hi im at same situation
@laurencei after changing my code to ur solution is also asserting that the expected notification was not sent
in my case this function in the core which in NotificationFake class
/**
* Get all of the notifications for a notifiable entity by type.
*
* @param mixed $notifiable
* @param string $notification
* @return array
*/
protected function notificationsFor($notifiable, $notification)
{
return $this->notifications[get_class($notifiable)][$notifiable->getKey()][$notification] ?? [];
}
is always says un-defined index \App\Models\User
what i have missed ?
@mohammedabdallah Have you tried following solution?
The
$useryou are putting in your test is _not_ the$userused in your register method - because in your register method you are creating a new$userYou need to do something like:
Notification::assertSentTo(User::latest()->first(), UserSubscribed::class);to get the latest user from the DB table and use that. I havent tested the code - you get the general idea.
But it is not a bug in the framework - so this issue should be closed.
Most helpful comment
The
$useryou are putting in your test is not the$userused in your register method - because in your register method you are creating a new$userYou need to do something like:
to get the latest user from the DB table and use that. I havent tested the code - you get the general idea.
But it is not a bug in the framework - so this issue should be closed.