如何测试 Laravel 资源

The*_*eky 2 api tdd unit-testing laravel laravel-resource

我正在测试一个带有分页的 API 端点返回的 Laravel 资源

 public function test_showing_all_plans(): void
 {
    $plans = Plan::where('is_active', true)
        ->paginate(10);

    $resource = PlansResource::collection($plans);

    $this->withHeaders([
        'Accept' => 'application/json',
        'Content-Type' => 'application/json',
        'AppKey' => 5,
    ])
        ->json('GET', '/api/customer/plans')
        ->assertStatus(200)
        ->assertExactJson([
            $resource->response()->getData(true),
        ]);
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是返回的结果不一样,因为端点的路径不等于资源的返回。

这是从端点返回的结果:

"links": {
        "first": "http://www.site.local/api/customer/plans?page=1",
        "last": "http://www.site.local/api/customer/plans?page=3",
        "next": "http://www.site.local/api/customer/plans?page=2",
        "prev": null
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 3,
        "path": "http://www.site.local/api/customer/plans",
        "per_page": 10,
        "to": 10,
        "total": 24
    }
Run Code Online (Sandbox Code Playgroud)

这是从资源“ $resource->response()->getData(true)”返回的代码

 "links": {
            "first": "http://www.site.local?page=1",
            "last": "http://www.site.local?page=3",
            "next": "http://www.site.local?page=2",
            "prev": null
        },
        "meta": {
            "current_page": 1,
            "from": 1,
            "last_page": 3,
            "path": "http://www.site.local",
            "per_page": 10,
            "to": 10,
          }
Run Code Online (Sandbox Code Playgroud)

那么如何将端点传递给我的代码,或者如何使它们相等,是否有适当的方法来测试 Laravel 资源?

Ste*_*ell 6

答案在于JsonResource::response()方法——该方法接受一个可选Illuminate\Http\Request $request参数,它将提供有关您尝试使用资源的位置的上下文。

调用$this->json('GET', '/api/customer/plans')将产生一个类似于这样的请求对象(为简洁起见被大量截断):

Illuminate\Http\Request {
  pathInfo: "/api/customer/plans"
  requestUri: "/api/customer/plans"
  method: "GET"
}
Run Code Online (Sandbox Code Playgroud)

同时,如果在解析 API 资源时没有提供 Request 对象,Laravel 将使用默认值创建一个新对象,看起来更像这样:

Illuminate\Http\Request {
  pathInfo: "/"
  requestUri: "/"
  method: "GET"
}
Run Code Online (Sandbox Code Playgroud)

为了确保这些匹配,您需要在测试用例中创建一个新的 Request 对象,它看起来像您所请求的内容,然后将其传递给$resource->response()调用:

Illuminate\Http\Request {
  pathInfo: "/api/customer/plans"
  requestUri: "/api/customer/plans"
  method: "GET"
}
Run Code Online (Sandbox Code Playgroud)