如何为Laravel中的GraphQL应用编写单元测试?
嘿,我来帮你梳理下Laravel中GraphQL应用的单元测试方案——当然不止用PHPUnit发简单请求啦,有好几种更优雅的方式可以选择,结合你给出的ClientQuery代码,我给你拆解几个实用方案:
Laravel GraphQL应用单元测试的进阶方案
1. 直接测试Resolver逻辑(单元测试核心)
其实你完全可以跳过HTTP请求层,直接实例化你的Query类,调用resolve方法来测试业务逻辑,这样测试更聚焦核心逻辑,运行速度也更快。
针对你的ClientQuery,可以这么写测试:
use Tests\TestCase; use App\GraphQL\Queries\ClientQuery; use App\Models\Client; use GraphQL\Type\Definition\ResolveInfo; class ClientQueryTest extends TestCase { public function test_resolve_returns_correct_client() { // 先创建测试数据 $client = Client::factory()->create(); // 实例化Query类 $query = new ClientQuery(); // 模拟resolve需要的参数(root和context可以传空数组,ResolveInfo直接mock) $resolveInfo = $this->createMock(ResolveInfo::class); // 调用resolve方法 $result = $query->resolve([], ['id' => $client->id], [], $resolveInfo); // 断言结果符合预期 $this->assertEquals($client->id, $result->id); $this->assertInstanceOf(Client::class, $result); } public function test_resolve_returns_null_for_nonexistent_id() { $query = new ClientQuery(); $resolveInfo = $this->createMock(ResolveInfo::class); $result = $query->resolve([], ['id' => 9999], [], $resolveInfo); $this->assertNull($result); } }
这种方式直接测试核心业务逻辑,不需要启动整个HTTP服务,测试效率拉满。
2. 测试完整GraphQL请求链路
如果你想覆盖Schema验证、参数校验等全链路场景,用PHPUnit发送GraphQL请求也是不错的选择,甚至可以借助Laravel GraphQL常用包(比如rebing/graphql-laravel)的辅助能力简化代码。
比如这样写:
use Tests\TestCase; class ClientQueryGraphQLTest extends TestCase { public function test_client_query_with_valid_id() { $client = Client::factory()->create(); // 发送GraphQL查询请求 $response = $this->postJson('/graphql', [ 'query' => ' query GetClient($id: Int!) { client(id: $id) { id name email } } ', 'variables' => [ 'id' => $client->id ] ]); // 断言响应正确 $response->assertStatus(200) ->assertJson([ 'data' => [ 'client' => [ 'id' => $client->id, 'name' => $client->name, 'email' => $client->email ] ] ]); } public function test_client_query_with_invalid_id_type() { $response = $this->postJson('/graphql', [ 'query' => ' query GetClient($id: Int!) { client(id: $id) { id } } ', 'variables' => [ 'id' => 'not-a-number' // 传入不符合类型的参数 ] ]); // 断言返回参数错误提示 $response->assertStatus(200) ->assertJsonStructure([ 'errors' => [ '*' => [ 'message', 'locations' ] ] ]); } }
这种方式能确保你的GraphQL API对外表现完全符合预期,覆盖参数校验、类型转换等边界场景。
3. 测试Query的定义规范
除了业务逻辑,你还可以测试Query的args和type方法,确保参数定义和返回类型完全符合你的Schema设计:
use Tests\TestCase; use App\GraphQL\Queries\ClientQuery; use GraphQL\Type\Definition\Type; class ClientQueryDefinitionTest extends TestCase { public function test_query_has_correct_attributes() { $query = new ClientQuery(); $this->assertEquals('ClientQuery', $query->attributes['name']); $this->assertEquals('A query', $query->attributes['description']); } public function test_query_args_are_correct() { $query = new ClientQuery(); $args = $query->args(); // 断言id参数是必填的Int类型 $this->assertArrayHasKey('id', $args); $this->assertEquals(Type::nonNull(Type::int()), $args['id']['type']); } public function test_query_returns_correct_type() { $query = new ClientQuery(); $type = $query->type(); // 断言返回的是Client类型 $this->assertEquals('Client', $type->name); } }
这种测试能避免出现参数类型错误、返回类型不匹配这类低级但影响很大的问题。
总结一下
- 想快速测试核心业务逻辑?直接测试Resolver是最优选择,速度快且聚焦;
- 要验证API全链路行为?发送GraphQL请求测试端点能覆盖更多场景;
- 额外的定义测试可以确保你的Query完全符合Schema规范,提前规避潜在问题。
根据你的需求组合这些方案,就能全面覆盖你的GraphQL应用测试啦!
内容的提问来源于stack exchange,提问作者Vandemberg Lima
相关产品推荐
相关产品推荐

