Laravel 资源在单元测试时换行两次
Laravel resources wrap twice when unit testing
当我 运行 一个测试服时,我的测试 return 一个 ResourceCollection
失败了,因为数据被包装了两次,但当我 运行 它们单独时成功了。
我已经知道原因了
ResourceCollection
使用一个名为 wrap 的 static 变量,在测试之间,这个变量保持他的状态。
现在我需要修复它
将这两个方法作为 OrganizationsController
中的起点
/**
* @param Request $request
* @return OrganizationsResource
*/
public function index(Request $request): OrganizationsResource
{
return new OrganizationsResource(
Organization::paginate()
);
}
/**
* @param Request $request
* @param Organization $organization
* @return OrganizationResource
*/
public function show(Request $request, Organization $organization): OrganizationResource
{
OrganizationResource::withoutWrapping();
return new OrganizationResource($organization);
}
组织资源
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
class OrganizationsResource extends ResourceCollection
{
/**
* @param Request $request
* @return array
*/
public function toArray($request): array
{
return [
'data' => OrganizationResource::collection($this->collection),
];
}
}
和 OrganizationResource
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class OrganizationResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'type' => 'organization',
'attributes' => [
'name' => $this->resource->name,
],
];
}
}
这工作得很好 index 的响应将像这样构建:
{
"data": [
{"id": 1},{"id": 2}, ....
],
"links": {
"next": "http://...",
....
},
"meta": {
"current_page": 1,
....
}
}
正如预期的那样,show 将 return
{
"id": 1,
"type" "organization",
....
}
但是,当我 运行 我所有的单元测试时,我的 index(es) returns以下json(注意{"data":{"data"...
{
"data": {
"data": [
{"id": 1},{"id": 2}, ....
],
"links": {
"next": "http://...",
....
},
"meta": {
"current_page": 1,
....
}
}
}
这是一个测试,当单独 运行ning 时成功,但在 withoutWrapping
之后失败,因为在测试服中被调用一次
/** @test */
public function organizations_api_index_returns_valid_schema(): void
{
factory(Organization::class, 2)->create(['name' => 'My-Company']);
$this->json('get', '/organizations')->assertJsonSchema(base_path("{$this->schema}/organizations.json"));
}
如果您想了解 assertJsonSchema
,这是来自 sixlive/laravel-json-schema-assertions
临时解决方法
我运行在 phpunit.xml 中将 processIsolation
设置为 true
进行测试,但它非常慢
我对我的回答不满意,但如果我在 ResourceCollection 中手动设置 $wrap
,它会修复错误。
class OrganizationsResource extends ResourceCollection
{
public static $wrap = 'data';
/**
* @param Request $request
* @return array
*/
public function toArray($request): array
{
return [
'data' => OrganizationResource::collection($this->collection),
];
}
}
当我 运行 一个测试服时,我的测试 return 一个 ResourceCollection
失败了,因为数据被包装了两次,但当我 运行 它们单独时成功了。
我已经知道原因了
ResourceCollection
使用一个名为 wrap 的 static 变量,在测试之间,这个变量保持他的状态。
现在我需要修复它
将这两个方法作为 OrganizationsController
中的起点/**
* @param Request $request
* @return OrganizationsResource
*/
public function index(Request $request): OrganizationsResource
{
return new OrganizationsResource(
Organization::paginate()
);
}
/**
* @param Request $request
* @param Organization $organization
* @return OrganizationResource
*/
public function show(Request $request, Organization $organization): OrganizationResource
{
OrganizationResource::withoutWrapping();
return new OrganizationResource($organization);
}
组织资源
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
class OrganizationsResource extends ResourceCollection
{
/**
* @param Request $request
* @return array
*/
public function toArray($request): array
{
return [
'data' => OrganizationResource::collection($this->collection),
];
}
}
和 OrganizationResource
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class OrganizationResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'type' => 'organization',
'attributes' => [
'name' => $this->resource->name,
],
];
}
}
这工作得很好 index 的响应将像这样构建:
{
"data": [
{"id": 1},{"id": 2}, ....
],
"links": {
"next": "http://...",
....
},
"meta": {
"current_page": 1,
....
}
}
正如预期的那样,show 将 return
{
"id": 1,
"type" "organization",
....
}
但是,当我 运行 我所有的单元测试时,我的 index(es) returns以下json(注意{"data":{"data"...
{
"data": {
"data": [
{"id": 1},{"id": 2}, ....
],
"links": {
"next": "http://...",
....
},
"meta": {
"current_page": 1,
....
}
}
}
这是一个测试,当单独 运行ning 时成功,但在 withoutWrapping
之后失败,因为在测试服中被调用一次
/** @test */
public function organizations_api_index_returns_valid_schema(): void
{
factory(Organization::class, 2)->create(['name' => 'My-Company']);
$this->json('get', '/organizations')->assertJsonSchema(base_path("{$this->schema}/organizations.json"));
}
如果您想了解 assertJsonSchema
,这是来自 sixlive/laravel-json-schema-assertions
临时解决方法
我运行在 phpunit.xml 中将 processIsolation
设置为 true
进行测试,但它非常慢
我对我的回答不满意,但如果我在 ResourceCollection 中手动设置 $wrap
,它会修复错误。
class OrganizationsResource extends ResourceCollection
{
public static $wrap = 'data';
/**
* @param Request $request
* @return array
*/
public function toArray($request): array
{
return [
'data' => OrganizationResource::collection($this->collection),
];
}
}