编写 Lighthouse 5 的自动化测试用例,要在查询中使用变量时,报错:Syntax Error: Expected Name, found $,进而 Failed asserting that an array has the subset Array

1、参考网址:https://lighthouse-php.com/4/testing/phpunit.html#setup ,使用 PHPUnit 进行测试。在 Lighthouse 中,通过 PHPUnit 添加自动化测试是很容易的。

2、运行 GraphQL Query API,响应 200。主要测试字段:themeAssets 的响应。如图1

图1

3、编辑 /Modules/ThemeStore/Tests/Functional/GraphQl/OnlineStoreThemeGraphQlApiTest.php ,代码如下

<?php

namespace Modules\ThemeStore\Tests\Functional\GraphQl;

use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Nuwave\Lighthouse\Testing\ClearsSchemaCache;
use Tests\CreatesApplication;

class OnlineStoreThemeGraphQlApiTest extends BaseTestCase
{
    use CreatesApplication,
        ClearsSchemaCache,
        MakesGraphQLRequests;

    public function testGetThemeById(): void
    {
        $response = $this->graphQL('
            {
                query GetThemeById($id: ID!) {
                    onlineStoreTheme(themeId: $id) {
                        id
                        editable
                        createdAt
                        name
                    }
                }
            }
            ',
            [
                'id' => 'vogue',
            ]
        );

        $response->assertJson([
            'data' => [
                'onlineStoreTheme' => [
                    'id' => 'vogue'
                ],
            ],
        ]);
    }

    protected function setUp(): void
    {
        parent::setUp();

        $this->bootClearsSchemaCache();
    }
}



4、执行命令:./vendor/bin/phpunit .\Modules\ThemeStore\Tests\Functional\GraphQl\OnlineStoreThemeGraphQlApiTest.php 。报错:Failed asserting that an array has the subset Array 。如图2

图2

PS E:\wwwroot\object> ./vendor/bin/phpunit .\Modules\ThemeStore\Tests\Functional\GraphQl\OnlineStoreThemeGraphQlApiTest.php

PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 919 ms, Memory: 56.00 MB

There was 1 failure:

1) Modules\ThemeStore\Tests\Functional\GraphQl\OnlineStoreThemeGraphQlApiTest::testGetThemeById
Unable to find JSON:

[{
    "data": {
        "onlineStoreTheme": {
            "id": "vogue"
        }
    }
}]

within response JSON:

[{
    "errors": [
        {
            "message": "Syntax Error: Expected Name, found $",
            "extensions": {
                "category": "graphql"
            },
            "locations": [
                {
                    "line": 3,
                    "column": 36
                }
            ]
        }
    ]
}].


Failed asserting that an array has the subset Array &0 (
    'data' => Array &1 (
        'onlineStoreTheme' => Array &2 (
            'id' => 'vogue'
        )
    )
).
--- Expected
+++ Actual
@@ @@
       ),
     ),
   ),
-  'data' =>
-  array (
-    'onlineStoreTheme' =>
-    array (
-      'id' => 'vogue',
-    ),
-  ),
 )

E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Assert.php:108
E:\wwwroot\object\vendor\laravel\framework\src\Illuminate\Foundation\Testing\TestResponse.php:479
E:\wwwroot\object\Modules\ThemeStore\Tests\Functional\GraphQl\OnlineStoreThemeGraphQlApiTest.php:38
phpvfscomposer://E:\wwwroot\object\vendor\phpunit\phpunit\phpunit:60

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
PS E:\wwwroot\object>

5、根源在于 响应 与 手动发送请求的响应不一致所导致。决定先编写一个不带参数的测试用例。/tests/Feature/PostsGraphQlApiTest.php

<?php

namespace Tests\Feature;

use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Nuwave\Lighthouse\Testing\ClearsSchemaCache;
use Tests\CreatesApplication;
use App\Models\Post;

class PostsGraphQlApiTest extends BaseTestCase
{
    use CreatesApplication,
        ClearsSchemaCache,
        MakesGraphQLRequests;

    public function testQueriesPosts(): void
    {
        $post = Post::factory()->create();
        $response = $this->graphQL('
            {
                posts {
                    id
                    title
                    content
                }
            }
        ');

        $response->assertJson([
            'data' => [
                'posts' => [
                    [
                        'id' => $post->id,
                        'title' => $post->title,
                        'content' => $post->content,
                    ]
                ],
            ],
        ]);
    }

    protected function setUp(): void
    {
        parent::setUp();

        $this->bootClearsSchemaCache();
    }
}



6、运行测试:./vendor/bin/phpunit .\tests\Feature\PostsGraphQlApiTest.php ,报错:Failed asserting that an array has the subset Array。但是响应确定是 JSON 的结构的,只不过未匹配上第一个元素。如图3

图3

            {
                "id": "104",
                "title": "Tenetur id labore dolores aperiam.",
it vel ut corrupti repellat quaerat. Et eos exercitationem voluptatem ut."
            },
            {
                "id": "105",
                "title": "Incidunt nulla libero officia aliquam dolor ut.",
                "content": "Molestiae harum velit numquam atque qui consequatur quam. Et sequi voluptatem sunt. Nemo et quo quod consequuntur. Quis eos consequatur recusandae in doloribus rerum odit odio."
            }
        ]
    }
}].


Failed asserting that an array has the subset Array &0 (
    'data' => Array &1 (
        'posts' => Array &2 (
            0 => Array &3 (
                'id' => 105
                'title' => 'Incidunt nulla libero officia aliquam dolor ut.'
                'content' => 'Molestiae harum velit numquam atque qui consequatur quam. Et sequi voluptatem sunt. Nemo et quo quod consequuntur. Quis eos consequatur recusandae in doloribus rerum odit odio.'
            )
        )
    )
).
--- Expected
+++ Actual

     array (
       0 =>
       array (
-        'id' => 105,
-        'title' => 'Incidunt nulla libero officia aliquam dolor ut.',
-        'content' => 'Molestiae harum velit numquam atque qui consequatur quam. Et sequi voluptatem sunt. Nemo et quo quod consequuntur. Quis eos consequatur recusandae in doloribus rerum odit odio.',
+        'id' => '1',
+        'title' => 'Optio earum deserunt fuga qui quia hic.',
+        'content' => 'Fuga molestiae quis sit quis maiores et. Amet eveniet sint quidem deleniti voluptas necessitatibus. Aut aut voluptatibus ut maiores doloremque eos totam.',
       ),
       1 =>
       array (

E:\wwwroot\lighthouse-tutorial\vendor\laravel\framework\src\Illuminate\Testing\Constraints\ArraySubset.php:85
E:\wwwroot\lighthouse-tutorial\vendor\laravel\framework\src\Illuminate\Testing\Assert.php:40
E:\wwwroot\lighthouse-tutorial\vendor\laravel\framework\src\Illuminate\Testing\AssertableJsonString.php:273
E:\wwwroot\lighthouse-tutorial\vendor\laravel\framework\src\Illuminate\Testing\TestResponse.php:695
E:\wwwroot\lighthouse-tutorial\tests\Feature\PostsGraphQlApiTest.php:36
phpvfscomposer://E:\wwwroot\lighthouse-tutorial\vendor\phpunit\phpunit\phpunit:97

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

7、获取 $posts 数组的最后一个键值,然后匹配成功。运行测试通过。如图4

图4

<?php

namespace Tests\Feature;

use Nuwave\Lighthouse\Testing\MakesGraphQLRequests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Nuwave\Lighthouse\Testing\ClearsSchemaCache;
use Tests\CreatesApplication;
use App\Models\Post;

class PostsGraphQlApiTest extends BaseTestCase
{
    use CreatesApplication,
        ClearsSchemaCache,
        MakesGraphQLRequests;

    public function testQueriesPosts(): void
    {
        $post = Post::factory()->create();
        $response = $this->graphQL('
            {
                posts {
                    id
                    title
                    content
                }
            }
        ');

        $responsePosts = $response->json("data.posts");
        $lastKey = array_key_last($responsePosts);

        $response->assertJson([
            'data' => [
                'posts' => [
                    $lastKey => [
                        'id' => $post->id,
                        'title' => $post->title,
                        'content' => $post->content,
                    ]
                ],
            ],
        ]);
    }

    protected function setUp(): void
    {
        parent::setUp();

        $this->bootClearsSchemaCache();
    }
}



PS E:\wwwroot\lighthouse-tutorial> ./vendor/bin/phpunit .\tests\Feature\PostsGraphQlApiTest.php
PHPUnit 9.5.11 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:00.434, Memory: 38.00 MB

OK (1 test, 1 assertion)
PS E:\wwwroot\lighthouse-tutorial>

8、打印响应对象。

PS E:\wwwroot\lighthouse-tutorial> ./vendor/bin/phpunit .\tests\Feature\UsersGraphQlApiTest.php
PHPUnit 9.5.11 by Sebastian Bergmann and contributors.

Illuminate\Testing\TestResponse Object
(
    [baseResponse] => Illuminate\Http\Response Object
        (
            [headers] => Symfony\Component\HttpFoundation\ResponseHeaderBag Object
                (
                    [computedCacheControl:protected] => Array
                        (
                            [no-cache] => 1
                            [private] => 1
                        )

                    [cookies:protected] => Array
                        (
                        )

                    [headerNames:protected] => Array
                        (
                            [cache-control] => Cache-Control
                            [date] => Date
                            [content-type] => Content-Type
                        )

                    [headers:protected] => Array
                        (
                            [cache-control] => Array
                                (
                                    [0] => no-cache, private
                                )

                            [date] => Array
                                (
                                    [0] => Thu, 20 Jan 2022 06:33:46 GMT
                                )

                            [content-type] => Array
                                (
                                    [0] => application/json
                                )

                        )

                    [cacheControl:protected] => Array
                        (
                        )

                )

            [content:protected] => {"errors":[{"message":"Syntax Error: Expected Name, found $","extensions":{"category":"graphql"},"locations":[{"line":3,"column":36}]}]}
            [version:protected] => 1.1
            [statusCode:protected] => 200
            [statusText:protected] => OK
            [charset:protected] =>
            [original] => Array
                (
                    [errors] => Array
                        (
                            [0] => Array
                                (
                                    [message] => Syntax Error: Expected Name, found $
                                    [extensions] => Array
                                        (
                                            [category] => graphql
                                        )

                                    [locations] => Array
                                        (
                                            [0] => Array
                                                (
                                                    [line] => 3
                                                    [column] => 36
                                                )

                                        )

                                )

                        )

                )

            [exception] =>
        )

    [exceptions:protected] => Illuminate\Testing\LoggedExceptionCollection Object
        (
            [items:protected] => Array
                (
                )

            [escapeWhenCastingToString:protected] =>
        )

    [streamedContent:protected] =>
)
PS E:\wwwroot\lighthouse-tutorial>

9、最后发现根源在于花括号多了一层。如图5

图5

    public function testGetThemeById(): void
    {
        $response = $this->graphQL('
            query GetThemeById($id: ID!) {
                onlineStoreTheme(themeId: $id) {
                    id
                    editable
                    createdAt
                    name
                }
            }
            ',
            [
                'id' => 'vogue',
            ]
        );

        $response->assertJson([
            'data' => [
                'onlineStoreTheme' => [
                    'id' => 'vogue'
                ],
            ],
        ]);
    }

10、运行测试,测试通过。如图6

图6

PS E:\wwwroot\object> ./vendor/bin/phpunit .\Modules\ThemeStore\Tests\Functional\GraphQl\OnlineStoreThemeGraphQlApiTest.php
PHPUnit 7.5.20 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 1.69 seconds, Memory: 60.00 MB

OK (1 test, 1 assertion)
PS E:\wwwroot\object>
永夜