在 PHPUnit 中调用路由时如何在 Laravel 8 中模拟 Eloquent 模型
How to mock Eloquent Model in Laravel 8 when calling a route in PHPUnit
我正在尝试模拟模型中的方法,以便我能够使用不同的场景测试控制器 api 端点。
我目前正在使用 Laravel 8 PhpUnit 和 Mockery 包。
在路由中我使用的是路由模型绑定。
api.php
Route::get('/api/{project}', [ProjectController::class, 'show']);
ProjectController.php
class ProjectController extends Controller
{
public function show(Project $project)
{
$state = $project->getState();
return response()->json($state);
}
}
ProjectControllerTest.php
class ProjectControllerTest extends TestCase
{
/**
* @test
* @group ProjectController
*/
public function shouldReturn200ForValidProjectGuid()
{
$project = Project::factory()->create();
$mock = Mockery::mock(Project::class);
// I have also tried this, see error below
// $mock = Mockery::mock(Project::class)->makePartial();
$this->app->instance(Project::class, $mock);
$mock->shouldReceive('getState')->andReturn('New South Wales');
$response = $this->getJson("/api/{$project->guid}");
$response->assertStatus(200)
->assertJson([
'data' => 'New South Wales'
]);
}
}
我目前遇到这个错误
Received Mockery_0_App_Models_Project::resolveRouteBinding(), but no expectations were specified Exception caught at [/usr/src/app/vendor/mockery/mockery/library/Mockery/Loader/EvalLoader.php(34) : eval()'d code@924
我尝试了其他选项,例如 makePartial(),但它也会导致以下错误
Received Mockery_0_App_Models_Project::__construct(), but no expectations were specified Exception caught at [/usr/src/app/vendor/mockery/mockery/library/Mockery/Loader/EvalLoader.php(34) : eval()'d code@924
非常感谢任何帮助,谢谢
您没有模拟模型,您已经在使用 Factory
所以您仍然使用它在您的模型上创建“模拟”数据。
$project = Project::factory()->create(['state' => 'New South Wales']);
阅读 Laravel 中有关工厂和单元测试的更多信息。看官方文档。
您可以尝试以下方法。我稍微更改了控制器响应以使其与 assertJson()
.
一起使用
web.php
Route::get('/projects/{project}', [ProjectController::class, 'show']);
项目控制器
<?php
namespace App\Http\Controllers;
use App\Models\Project;
class ProjectController extends Controller
{
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Project $project)
{
return response()->json([
'state' => $project->getState()
]);
}
}
ProjectControllerTest
<?php
namespace Tests\Feature;
use App\Models\Project;
use Mockery;
use Tests\TestCase;
class ProjectControllerTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function test_example()
{
$mock = Mockery::mock(Project::class)->makePartial();
$mock->shouldReceive('resolveRouteBinding')->andReturnSelf();
$mock->shouldReceive('getState')->andReturn('NSW');
$this->app->instance(Project::class, $mock);
$response = $this->get('/projects/1');
$response->assertStatus(200)
->assertJson([
'state' => 'NSW'
]);
}
}
我正在尝试模拟模型中的方法,以便我能够使用不同的场景测试控制器 api 端点。
我目前正在使用 Laravel 8 PhpUnit 和 Mockery 包。 在路由中我使用的是路由模型绑定。
api.php
Route::get('/api/{project}', [ProjectController::class, 'show']);
ProjectController.php
class ProjectController extends Controller
{
public function show(Project $project)
{
$state = $project->getState();
return response()->json($state);
}
}
ProjectControllerTest.php
class ProjectControllerTest extends TestCase
{
/**
* @test
* @group ProjectController
*/
public function shouldReturn200ForValidProjectGuid()
{
$project = Project::factory()->create();
$mock = Mockery::mock(Project::class);
// I have also tried this, see error below
// $mock = Mockery::mock(Project::class)->makePartial();
$this->app->instance(Project::class, $mock);
$mock->shouldReceive('getState')->andReturn('New South Wales');
$response = $this->getJson("/api/{$project->guid}");
$response->assertStatus(200)
->assertJson([
'data' => 'New South Wales'
]);
}
}
我目前遇到这个错误
Received Mockery_0_App_Models_Project::resolveRouteBinding(), but no expectations were specified Exception caught at [/usr/src/app/vendor/mockery/mockery/library/Mockery/Loader/EvalLoader.php(34) : eval()'d code@924
我尝试了其他选项,例如 makePartial(),但它也会导致以下错误
Received Mockery_0_App_Models_Project::__construct(), but no expectations were specified Exception caught at [/usr/src/app/vendor/mockery/mockery/library/Mockery/Loader/EvalLoader.php(34) : eval()'d code@924
非常感谢任何帮助,谢谢
您没有模拟模型,您已经在使用 Factory
所以您仍然使用它在您的模型上创建“模拟”数据。
$project = Project::factory()->create(['state' => 'New South Wales']);
阅读 Laravel 中有关工厂和单元测试的更多信息。看官方文档。
您可以尝试以下方法。我稍微更改了控制器响应以使其与 assertJson()
.
web.php
Route::get('/projects/{project}', [ProjectController::class, 'show']);
项目控制器
<?php
namespace App\Http\Controllers;
use App\Models\Project;
class ProjectController extends Controller
{
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Project $project)
{
return response()->json([
'state' => $project->getState()
]);
}
}
ProjectControllerTest
<?php
namespace Tests\Feature;
use App\Models\Project;
use Mockery;
use Tests\TestCase;
class ProjectControllerTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function test_example()
{
$mock = Mockery::mock(Project::class)->makePartial();
$mock->shouldReceive('resolveRouteBinding')->andReturnSelf();
$mock->shouldReceive('getState')->andReturn('NSW');
$this->app->instance(Project::class, $mock);
$response = $this->get('/projects/1');
$response->assertStatus(200)
->assertJson([
'state' => 'NSW'
]);
}
}