Can you show the complete class? Are you sure you are importing the facade?
Notification::fake() throwing TypeError: Illegal offset type
Hi all, I'm writing a test that test an endpoint. In this endpoint I send an email notification.
When I add
Notification::fake()
The test fail with the following error:
TypeError: Illegal offset type
Anyone has any hint?
@Sinnbeck I'm using Pest and importing the facade
use Illuminate\Support\Facades\Notification;
@rossiluca what file/line is the error in? Stack trace?
Here:
TypeError: Illegal offset type in /path-to-my-project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php:329
Stack trace:
#0 /path-to-my-project/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/NotificationFake.php(294): Illuminate\Support\Testing\Fakes\NotificationFake->sendNow(Array, Object(App\Notifications\MyNotification))
@rossiluca can you show the test and the notification ?
@Sinnbeck This is the test
test('why my test is not working', function () {
$user = User::factory()->make();
Notification::fake();
login()
->post('/api/myendpoint/export')
->assertStatus(201)
->assertJson(['message' => 'Export sent successfully', 'status' => 'success']);
Notification::assertSentTo(
$user, MyNotification::class
);
});
The notification is a brand-new standard Notification.
@rossiluca try wrapping user in []. https://laravel.com/docs/9.x/mocking#notification-fake
Notification::assertSentTo(
[$user], MyNotification::class
);
@Sinnbeck Yep, tried it before, didn't change
@rossiluca can you show the code that sends the notification? It's this line that breaks https://github.com/laravel/framework/blob/9.x/src/Illuminate/Support/Testing/Fakes/NotificationFake.php#L329
@Sinnbeck This is the controller function that send the notification
public function __invoke(Request $request)
{
$request->user()->notify(new MyNotification());
return response()->json([
'message' => 'Export sent successfully',
'status' => 'success',
], 201);
}
And this is the notification
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class MyNotification 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)
->line("This is the email body");
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
@rossiluca hmm cannot see the error. Did you change the user model so it returns some strange ID?
Can you try
dd($request->user()->getKey());
@Sinnbeck I'm using uuid so this is the response
Ramsey\Uuid\Lazy\LazyUuidFromString {#1774 // app/Http/Controllers/API/MyController.php:14
-unwrapped: null
-uuid: "19af3b3c-dca5-4947-9910-2ae1842bebf6"
uuid: "19af3b3c-dca5-4947-9910-2ae1842bebf6"
}
@rossiluca Oh interesting. That might very well be the issue here. It gets a class, not a string back. Can you show the user model ?
Btw. You can try recreating the issue yourself.
$foo['19af3b3c-dca5-4947-9910-2ae1842bebf6'] = 'bar';
$bar = $foo[$request->user()->getKey()];
@Sinnbeck
Sure, not much inside right, now. Only the boot method to creare the uuid
namespace App\Models;
use App\Traits\UuidTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable, UuidTrait, HasRoles;
public $incrementing = false;
protected $keyType = 'string';
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public static function boot()
{
parent::boot();
static::creating(function ($issue) {
$issue->id = Str::uuid(36);
});
}
}
@rossiluca Try casting it
static::creating(function ($issue) {
$issue->id = (string) Str::uuid(36);
});
@sinnbeck Nicee, this works! Thanks a lot! Lost half of a day trying to resolve the issue 😅
Thank you very much
@rossiluca Happy to help :) It was a bit tricky indeed
@rossiluca I had this problem today (Laravel 10). I'm also using uuids as unique keys and using the Trait Illuminate\Database\Eloquent\Concerns\HasUuids; on the models. As the uuid is generated automatically by the trait, to fix the problem, I inserted:
protected $casts = [
'id' => 'string',
];
Hope that helps someone in the future
Please or to participate in this conversation.