即使Postman做得对,测试也无法正确断言请求

时间:2018-02-21 23:35:03

标签: php laravel testing laravel-5 laravel-5.5

晚安,我在这里遇到一点麻烦。我是第一次做TDD,所以我不知道这种行为的根源。这篇文章似乎很长,但主要是因为我复制了相关代码的等值。

案例

顺便说一句,我使用Laravel作为后端制作应用程序。

我正在测试User角色为admin的{​​{1}}可以创建'设施'对象,但其他用户不能。非常基本的东西。

问题

在测试端点时,它允许具有角色user(常规端点)的用户创建对象。但是当我尝试使用Postman测试它时,它应该是:阻止请求。

使用Laratrust软件包来管理acl(它运行良好,已经测试过了)。

代码

routes / api.php //这已经有了中间件:auth& API

Route::post('api/v1/facilities', 'FacilityController@store');

应用\ HTPP \控制器\ FacilityController.php

use App\Http\Requests\Facility\CreateFacilityRequest;
use App\Http\Resources\FacilityResource;
use App\Repositories\FacilityRepository;
use App\Services\ImageService;
use Illuminate\Http\Response;

// some code

/**
 * Create a new Facility
 *
 * @param CreateFacilityRequest $request
 * @return \Illuminate\Http\JsonResponse
 */
public function store(CreateFacilityRequest $request)
{
    $data = $request->only(['name']);
    $file = $request->file('image');
    $data['image'] = ImageService::storeAs('images/facilities', $file, 'friendly', $data['name']);

    $facility = $this->facilityRepository->create($data);

    return response()->json([
        "message" => "The facility has been added.",
        "data"    => new FacilityResource($facility)
    ], Response::HTTP_CREATED);
}

应用\ HTTP \请求\设施\ CreateFacilityRequest.php

class CreateFacilityRequest extends FormRequest {

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return auth()->user()->can('create-facilities');
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name'  => 'required|string|unique:facilities,name',
            'image' => 'required|image'
        ];
    }
}

最后,这是我的测试:

测试\特征\ FacilityTest.php

/**
     * @test
     * Test for: a Facility can be registered only by an admin.
     */
    public function a_facility_can_be_registered_only_by_an_admin()
    {
        /** Given a correct information for a facility */
        \Storage::fake('public');
        $data = ["name" => "Facility A", 'image' => UploadedFile::fake()->image('facility-a.jpg') ];

        /** When the request is made by an admin */
        $admin = $this->createUser([], 'admin');
        $response = $this->apiAs($admin, 'POST','/api/v1/facilities', $data);

        /** Then the facility should be registered */
        $response->assertStatus(Response::HTTP_CREATED); // 201

        /** When the request is made by somebody else */
        $data = ["name" => "Facility B", 'image' =>UploadedFile::fake()->image('facility-b.jpg') ];
        $regular_user = $this->createUser([], 'user');
        $response = $this->apiAs($regular_user, 'POST','/api/v1/facilities', $data);

        /** Then the request should be declined */
        $this->assertTrue($regular_user->hasRole('user'));
        $this->assertFalse($regular_user->can('create-facilities'));

        $response->assertStatus(Response::HTTP_FORBIDDEN); // 403
        \Storage::disk('facilities')->assertMissing('facility-b.jpg');
    }

除了这一个之外,所有的断言都被确认了:

$response->assertStatus(Response::HTTP_FORBIDDEN); // 403

输出是这样的:

  

预期状态代码403但收到201。

     

声明false为真的失败。

     

时间:447毫秒,内存:20.00MB

     

FAILURES!测试:1,断言:4,失败:1。

     

使用退出代码1完成处理

当我dd($response->json())时,它返回成功通话的常规json。但在邮递员中,它会返回正确的一个:

{
    "message" : "Unauthorized" // with status code 403
}

有人知道为什么吗?

更新

受保护的功能apiAs()

protected function apiAs($user, $method, $uri, array $data = [], array $headers = []) : TestResponse
    {
        $headers = array_merge([
            'Authorization' => 'Bearer '.\JWTAuth::fromUser($user),
            'Accept' => 'application/json'
        ], $headers);

        return $this->api($method, $uri, $data, $headers);
    }


    protected function api($method, $uri, array $data = [], array $headers = [])
    {
        return $this->json($method, $uri, $data, $headers);
    }

1 个答案:

答案 0 :(得分:2)

这是因为您正在使用jwt-auth apiAs()方法缓存与此行上的响应相关联的用户标识符:

'Authorization' => 'Bearer '.\JWTAuth::fromUser($user),

这会导致您的$response变量(第二次以普通用户身份获取API)返回管理员的第一个缓存数据。

我会将这些断言分成单独的测试,以及您的命名当前是a_facility_can_be_registered_only_by_an_admin()a_facility_cannot_be_registered_by_a_user_that_is_not_an_admin()可能是一个适用的名称,可以绕过此缓存。