web.php
中定义的路线是
Route::get('about-us', [PageController::class, 'renderAboutUsPage'])->name('pages.about-us');
在我的控制器中,我有方法
class PageController extends Controller
{
protected $pageService;
/**
* Class contructor
*/
public function __construct(PageService $pageService)
{
$this->pageService = $pageService;
}
/**
* Method to render about us page
*/
public function renderAboutUsPage(){
return $this->renderStaticPage('about-us');
}
/**
* Method to render static page
* @param slug
*/
private function renderStaticPage($slug) {
Log::info("Rendering ".$slug." static page.");
$page = $this->pageService->getActivePageBySlug($slug);
return view('pages.static-page', ['data'=>$page]);
}
}
当我测试方法时,我的理解是这样的
renderAboutUsPage()
那么我应该在测试中模拟 pageService->getActivePageBySlug($slug)
,这样就可以避免真正调用这个方法。这将有助于减少测试执行时间。
我的服务有单独的测试,我正在独立测试
getActivePageBySlug()
。
我的测试用例是
/**
* @test
* @testdox Whether the about us page returns a successful response, renders the correct view, contains view object {data} and log correct messages in log file.
* @group website
* @group static-pages
*/
public function test_whether_about_us_page_renders_successfully()
{
Log::shouldReceive('info')->once()->with("Rendering about-us static page.");
Log::shouldReceive('info')->once()->with("Getting page by active status and provided slug.");
$response = $this->get('about-us');
$response->assertStatus(200);
$response->assertViewIs('pages.static-page');
$response->assertViewHas('data');
}
我不知道如何在我的测试用例中模拟方法
getActivePageBySlug($slug)
以避免真正的调用。
getActivePageBySlug($slug)
方法的定义是:
/**
* Method to get page by slug (Checks to page status is active)
* @param string slug
* @return Page page
* @throws Throwable e
*/
public function getActivePageBySlug(string $slug)
{
Log::info("Getting page by active status and provided slug.");
try
{
$page = Page::where('slug',$slug)->where('status', Status::active->value())->first();
if(!$page) {
throw new NotFoundHttpException("The page ". $slug ." not found.");
}
return $page;
}
catch (Throwable $e)
{
Log::error("Error in getting page by slug.");
throw $e;
}
}
实际上,您不想避免调用,否则它并不是真正的功能测试,而是“单元测试”。如果您正在项目中测试端点/url,那么它应该是功能测试,您应该进行真正的调用,除非它是您真正想避免调用的第三方服务。
您的服务正在执行数据库调用,您应该调用它,这很好,特别是您在调用之后没有做任何繁重的工作。
所以,如果你想进行真正的调用,你应该有这样的代码(假设你有工厂并且一切都正确设置):
/**
* @group website
* @group static-pages
*/
public function test_about_us_page_should_render(): void
{
Page::factory()->create([
'slug' => $page = 'about-us',
'status' => Status::active, // Be sure to cast 'status' => Status::class in your model
]);
Log::shouldReceive('info')->once()->with("Rendering {$page} static page.");
Log::shouldReceive('info')->once()->with("Getting page by active status and provided slug.");
$this->get($page)
->assertOk()
->assertViewIs('pages.static-page')
->assertViewHas('data');
}
这应该是有史以来最简单的测试,您可以在那里添加更多东西。看到我更改了测试名称(试图遵循标准),以及其他小的更改。
现在,假设您还希望页面失败(您的服务抛出错误),所以我们也测试一下:
/**
* @group website
* @group static-pages
* @depends test_about_us_page_should_render
* @dataProvider pageErrorDataProvider
*/
public function test_about_us_page_should_throw_an_error_when_model_not_found(callable $pageSeeder): void
{
$pageSeeder();
$page = 'about-us';
Log::shouldReceive('error')->once()->with("Error in getting page by slug.");
$this->get($page)
->assertServerError(); // This checks for status = 500
// You should also assert that you got the exact error: "The page {$page} not found."
}
public function pageErrorDataProvider(): array
{
return [
'Page not active' => function () {
return Page::factory()->create([
'slug' => 'about-us',
'status' => Status::disabled, // Or whatever the other state is
]);
},
'Different page' => function () {
return Page::factory()->create([
'slug' => 'about',
'status' => Status::active,
]);
},
'Page does not exist' => function () {
return null;
},
];
}
现在,你可以看到我们首先依赖第一个测试,如果 happy path 有效,这个新的 case 也可以运行。我们还利用了数据提供者,因此我们使用相同的情况测试不同的可能性,只是不同的数据初始化。
我现在不记得从端点检查错误的正确断言是什么,所以我们还确保检查错误是否是预期的错误,但是请阅读官方文档并修改它并你会找到它的。
最后,如果您确实想避免进行任何通话,那么您的测试应该是:
/**
* @group website
* @group static-pages
*/
public function test_about_us_page_should_render(): void
{
$page = 'about-us';
$this->mock(PageService::class, function (MockInterface $mock) {
$mock->shouldReceive('getActivePageBySlug')
->andReturn(
Page::factory()->make([
'slug' => $page = 'about-us',
'status' => Status::active,
])
);
});
Log::shouldReceive('info')->once()->with("Rendering {$page} static page.");
Log::shouldReceive('info')->once()->with("Getting page by active status and provided slug.");
$this->get($page)
->assertOk()
->assertViewIs('pages.static-page')
->assertViewHas('data');
}
你想模拟服务,这样你就可以做任何事情。
请记住,我使用了 Laravel 11.x 文档,并且我不知道你的
Page
有什么内容,你还应该断言返回的内容是预期的内容,而不仅仅是它有 data
索引您的观点,以及它是什么数据。