【发布时间】:2026-02-15 18:45:01
【问题描述】:
我正在尝试为我编写的功能创建测试。
逻辑很简单:
我从 api.php 调用 store 方法:
Route::group(['prefix' => '/study/{study}/bookmark_list'], function () {
...
Route::post('/{bookmarkList}/bookmark', 'BookmarkController@store');
...
});
因此我正在注入研究和书签列表。
我的控制器传递参数
public function store(Study $study, BookmarkList $bookmarkList)
{
return $this->serve(CreateBookmarkFeature::class);
}
我相应地在功能中使用它们
'bookmark_list_id' => $request->bookmarkList->id,
class CreateBookmarkFeature extends Feature
{
public function handle(CreateBookmarkRequest $request)
{
//Call the appropriate job
$bookmark = $this->run(CreateBookmarkJob::class, [
'bookmark_list_id' => $request->bookmarkList->id,
'item_id' => $request->input('item_id'),
'type' => $request->input('type'),
'latest_update' => $request->input('latest_update'),
'notes' => $request->input('notes')
]);
//Return
return $this->run(RespondWithJsonJob::class, [
'data' => [
'bookmark' => $bookmark
]
]);
}
}
我还在使用自定义请求 (CreateBookmarkRequest),它实际上验证用户是否被授权并对输入施加一些规则。
class CreateBookmarkRequest extends JsonRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return $this->getAuthorizedUser()->canAccessStudy($this->study->id);
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
"item_id" => ["integer", "required"],
"type" => [Rule::in(BookmarkType::getValues()), "required"],
"latest_update" => ['date_format:Y-m-d H:i:s', 'nullable'],
"text" => ["string", "nullable"]
];
}
}
现在,问题来了。我想为测试返回正确响应的功能编写一个测试(最好验证 CreateBookmarkJob 是否被调用,但不是那么重要)。问题是虽然我可以模拟请求以及 input() 方法,但我无法模拟注入的 bookmarkList。
其余函数已正确模拟并按预期工作。
我的测试:
class CreateBookmarkFeatureTest extends TestCase
{
use WithoutMiddleware;
use DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
// seed the database
$this->seed();
}
public function test_createbookmarkfeature()
{
//GIVEN
$mockRequest = $this->mock(CreateBookmarkRequest::class);
$mockRequest->shouldReceive('authorize')->once()->andReturnTrue();
$mockRequest->shouldReceive('rules')->once()->andReturnTrue();
$mockRequest->shouldReceive('input')->once()->with('item_id')->andReturn(1);
$mockRequest->shouldReceive('input')->once()->with('type')->andReturn("ADVOCATE");
$mockRequest->shouldReceive('input')->once()->with('latest_update')->andReturn(Carbon::now());
$mockRequest->shouldReceive('input')->once()->with('notes')->andReturn("acs");
$mockRequest->shouldReceive('bookmark_list->id')->once()->andReturn(1);
//WHEN
$response = $this->postJson('/api/recruitment_toolkit/study/1/bookmark_list/1/bookmark', [
"type"=> "ADVOCATE",
"item_id"=> "12",
"text"=> "My first bookmark"
]);
//THEN
$this->assertEquals("foo", $response['data'], "das");
}
我认为一个可能的解决方案是不模拟请求,但这样我无法找到模拟请求中“returnAuthorisedUser”的方法。
任何关于如何模拟注入模型的想法都将不胜感激,或者任何关于如何正确测试功能的想法,以防我接近错误。
值得一提的是,我对每个作业(CreateBookmarkJob 和 RespondWithJSONJob)都有单独的单元测试。
提前致谢
【问题讨论】:
-
我的回答缺乏一些细节,因为不清楚你的控制器在做什么或它正在返回什么(不知道
Feature类是什么,或者你为什么要使用作业创建简单的对象) 但希望它能让你走上正轨。 -
作为@miken32 的回答,您还可以在另一篇文章中查看我的完全详细的(一般主题),但会帮助您更好地理解测试。它也是 miken32 答案的补充。 How to correctly test
标签: laravel unit-testing dependency-injection phpunit mockery