Laravel 8 上的 HTTP RESTful API 功能测试
Feature test for HTTP RESTful API on Laravel 8
我正在尝试在 RESTful API 中编写我在 laravel 8 中创建的功能测试。
我有 ChatController
通过 getUserChats
方法获取用户聊天:
// get chats for user
public function getUserChats()
{
$chats = $this->chats->getUserChats();
return ChatShowResource::collection($chats);
}
这条路线调用的:
Route::get('chats', [
App\Http\Controllers\Chats\ChatController::class, 'getUserChats'
]);
这是我在这条路线上的功能测试:
public function test_get_user_chats()
{
// creates the fake user
$user = User::factory()->create();
$this->actingAs($user, 'api');
// adds the chat to new fake user that created
$response_create_chat = $this->json('POST', '/api/chats', [
'recipient' => $user->username,
'body' => 'some chat text',
]
);
$response_create_chat
->assertStatus(201)
->assertJsonPath('data.body', 'some chat text');
$response_get_chats = $this->json('get', '/api/chats');
$response_get_chats->assertStatus(200);
}
测试通过这个绿色输出成功运行 OK (1 test, 3 assertions)
,但我不知道这是实现它的最佳方法。
所以问题是我在测试中还需要做些什么吗?我是否在进行正确的功能测试?
通常,您希望测试范围尽可能小。您提供的测试用例当前正在测试两个单独的 api 端点:
- 创建聊天
- 正在聊天
问题是如果与创建聊天相关的代码中断,与获取聊天相关的测试用例将失败。
我建议将它们分成两个单独的测试用例。这将使您相信,如果您的聊天测试用例失败,那是因为与聊天相关的代码失败,而不是与此端点无关的代码。
我还建议使用 setUp
和 tearDown
方法来确保您的测试用例使数据库保持与找到数据库时相同的状态。这确保其他测试用例不必关心来自该测试的数据。这意味着 setUp
方法应该做如下事情:
- 创建用户
- 创建聊天
tearDown
方法将负责删除用户和聊天。
此外,您应该测试端点输出的格式和数据。目前您只检查 200 响应代码。如果您的 api 更新为 return 用户列表而不是聊天列表,与获取聊天相关的测试用例仍会通过,因为它实际上并未验证正在 returned 的数据.
EX:
class GetChatsTest extends TestCase
{
private User $user;
public function testGetChats(): void
{
$chat = $this->json('get', '/api/chats');
// Check the chat's returned value
$this->assertSame('Some parameters', $chat);
}
protected function setUp(): void
{
parent::setUp();
// Create the user in the setup. This is run before each test method is run.
$this->user = User::factory()->create();
// Create the chat for the user (Pseudo code because I don't know how your code works)
$this->user->createChat('Some parameters');
}
protected function tearDown(): void
{
parent::tearDown();
// Delete the user and chats here, pseudocode again. This runs after every test method is run
$this->user->deleteChats();
$this->user->delete();
}
}
关于示例代码需要注意的一件事是它不使用其余部分 api 来创建用户或聊天,而是使用伪代码控制器方法来确保它不依赖于功能用于测试的聊天 api。
我正在尝试在 RESTful API 中编写我在 laravel 8 中创建的功能测试。
我有 ChatController
通过 getUserChats
方法获取用户聊天:
// get chats for user
public function getUserChats()
{
$chats = $this->chats->getUserChats();
return ChatShowResource::collection($chats);
}
这条路线调用的:
Route::get('chats', [
App\Http\Controllers\Chats\ChatController::class, 'getUserChats'
]);
这是我在这条路线上的功能测试:
public function test_get_user_chats()
{
// creates the fake user
$user = User::factory()->create();
$this->actingAs($user, 'api');
// adds the chat to new fake user that created
$response_create_chat = $this->json('POST', '/api/chats', [
'recipient' => $user->username,
'body' => 'some chat text',
]
);
$response_create_chat
->assertStatus(201)
->assertJsonPath('data.body', 'some chat text');
$response_get_chats = $this->json('get', '/api/chats');
$response_get_chats->assertStatus(200);
}
测试通过这个绿色输出成功运行 OK (1 test, 3 assertions)
,但我不知道这是实现它的最佳方法。
所以问题是我在测试中还需要做些什么吗?我是否在进行正确的功能测试?
通常,您希望测试范围尽可能小。您提供的测试用例当前正在测试两个单独的 api 端点:
- 创建聊天
- 正在聊天
问题是如果与创建聊天相关的代码中断,与获取聊天相关的测试用例将失败。
我建议将它们分成两个单独的测试用例。这将使您相信,如果您的聊天测试用例失败,那是因为与聊天相关的代码失败,而不是与此端点无关的代码。
我还建议使用 setUp
和 tearDown
方法来确保您的测试用例使数据库保持与找到数据库时相同的状态。这确保其他测试用例不必关心来自该测试的数据。这意味着 setUp
方法应该做如下事情:
- 创建用户
- 创建聊天
tearDown
方法将负责删除用户和聊天。
此外,您应该测试端点输出的格式和数据。目前您只检查 200 响应代码。如果您的 api 更新为 return 用户列表而不是聊天列表,与获取聊天相关的测试用例仍会通过,因为它实际上并未验证正在 returned 的数据.
EX:
class GetChatsTest extends TestCase
{
private User $user;
public function testGetChats(): void
{
$chat = $this->json('get', '/api/chats');
// Check the chat's returned value
$this->assertSame('Some parameters', $chat);
}
protected function setUp(): void
{
parent::setUp();
// Create the user in the setup. This is run before each test method is run.
$this->user = User::factory()->create();
// Create the chat for the user (Pseudo code because I don't know how your code works)
$this->user->createChat('Some parameters');
}
protected function tearDown(): void
{
parent::tearDown();
// Delete the user and chats here, pseudocode again. This runs after every test method is run
$this->user->deleteChats();
$this->user->delete();
}
}
关于示例代码需要注意的一件事是它不使用其余部分 api 来创建用户或聊天,而是使用伪代码控制器方法来确保它不依赖于功能用于测试的聊天 api。