Laravel-如何使用嘲弄来单元测试中间件更新用户数据



我有以下中间件来更新用户的last_seen_at字段,并且我只将其用于经过身份验证的用户可以调用的路由:

// app/Http/Middleware/LastSeen.php
public function handle($request, Closure $next)
{
$user = $request->user();
$user->last_seen_at = now();
$user->save();
return $next($request);
}
// app/Http/Kernel.php
protected $routeMiddleware = [
// other middleware
'lastseen' => AppHttpMiddlewareLastSeen::class
]
// routes/api.php
Route::group([
'middleware' => ['jwt', 'lastseen']
], function () {
// routes
});

我已经编写了以下用于测试中间件的单元测试:

// tests/Unit/LastSeenMiddlewareTest.php
/** @test */
public function doesLastSeenMiddlewareUpdateUsersLastSeenAt()
{
$user = Mockery::mock(User::class);
$user->shouldReceive('setAttribute')->passthru();
$user->shouldReceive('save')->once();
$user = $user->makePartial();
app()->instance(User::class, $user);
$request = Mockery::mock(Request::class)
->shouldReceive('user')
->once()
->andReturn()
->getMock();
$middleware = new LastSeen;
$middleware->handle($request, function () {});
}

通过运行测试,我得到一个错误:ErrorException: Creating default object from empty value。然而,我不理解这个问题,无法解决它

好吧,这个问题从一开始就很愚蠢。我错过了将$user作为模拟Requestuser方法的返回值。以下测试通过:

// tests/Unit/LastSeenMiddlewareTest.php
/** @test */
public function doesLastSeenMiddlewareUpdateUsersLastSeenAt()
{
$user = Mockery::mock(User::class);
/* As I'm making a partial mock,
I don't need to worry about passing
through the call to the setAttribute method */
$user->shouldReceive('save')->once();
$user = $user->makePartial();
app()->instance(User::class, $user);
$request = Mockery::mock(Request::class)
->shouldReceive('user')
->once()
->andReturn($user) // I should've passed $user here
->getMock();
$middleware = new LastSeen;
$middleware->handle($request, function () {});
$this->assertEqualsWithDelta($user->last_seen_at, now(), 1);
}

归根结底,middlaware只是一个带有handle方法的经典class
我将这样进行单元测试:

public function doesLastSeenMiddlewareUpdateUsersLastSeenAt()
{
//note: this is using the old factory syntax prior to Laravel 8 https://github.com/laravel/legacy-factories
$user = factory(User::class)->create(['last_seen_at' => now()->subHour()]);

//login as the user since in your middleware you get the logged user
$this->actingAs($user);

//get the middleware through the container
$middleware = app(LastSeen::class);

//call handle method
$middleware->handle(request(),  function () {});
$this->assertEqualsWithDelta($user->refresh()->last_seen_at, now(), 1);
}

最新更新