Laravel API 测试 - 如何测试具有外部 API 调用的 API

ARI*_*ANA 6 api phpunit unit-testing laravel laravel-5.2

我的 API 代码

public function store (Request $request, $profileId)
{
    $all = $request->all();
    $token = AccessToken::with('users')->where('access_token',$request->input('access_token'))->first();

    if($token && $token->users->isOwnProfile($profileId))
    {
        $rules = [
            'access_token'     => 'required',
            'title'            => 'required',
            'description'      => 'required',
            'file_id'          => 'required',
            'audience_control' => 'required|in:' . join(',', PostRepository::$AUDIENCE_CONTROL),
            'tags'             => 'required',
        ];
        $validator = Validator::make($all, $rules);

        $error = $validator->errors()->toArray();
        if ($validator->fails())
        {
            return $this->setStatusCode(401)
                ->setStatusMessage(trans('api.validation failed'))
                ->respondValidationMessage($error);
        }
        try {
            $response = $this->postRepository->save($request, $profileId);
            if(isset($response['error']))
                return $this->messageSet([
                    'message' => $response['error']['message'],
                ], $response['error']['status_code']);

            return $this->setDataType('post_id')
                ->setStatusCode('200')
                ->respondWithCreatedId(trans('api.Post created'), $response->id);
        } catch (\Exception $e) {
            return $this->respondInternalError(trans('api.processing error'));
        }
    }
    return $this->respondInternalError('404 page');

}
Run Code Online (Sandbox Code Playgroud)

从 save 方法调用另一个调用外部 API 的方法。

/*
 * this function returns some response where it has profile_id for 
 * the file which in other save function is matched that the
 * profile_id passed as parameter is same with file profile_id
 */
public function getFileDetails($file_id)
{
    try
    {
        $response = json_decode((new Client())->request('GET', env('xyz','http://abc.xyz/api/v1').'/files/' . $file_id)->getBody()->getContents(), true);
    }
    catch (RequestException $e)
    {
        $response = json_decode($e->getResponse()->getBody()->getContents(), true);
    }

    return $response;

}
Run Code Online (Sandbox Code Playgroud)

现在这是我的 API 测试函数。

public function testPostCreateChecksProfileMatchesCorrectly()
{
    $this->json('POST', 'profiles/' . $this->getProfile()->id . '/posts' . '?access_token=' . $this->getAccessToken(), [
        'title' => 'api testing title',
        'description' => 'api testing description',
        'audience_control' => 'public',
        'tags' => [
            'Animals',
            'City'
        ],
        'file_id' => '281'
    ])->seeJsonStructure([
        'success' => [
            'message',
            'post_id',
            'status',
        ],
    ]);
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题是如何 在测试时为外部API创建虚假响应

我正在使用PHPUnit& Laravel 5.2

小智 -5

首先,永远不要测试你不拥有的东西。外部 API 调用是不属于您的想法。可能有上千个问题或用例可能会出错,例如您提交的数据、网络错误或其内部错误。对于每种情况你都应该测试情况,这是乏味的。而是使用 moc 对象并对此寄予一些期望。收听这个播客,http://www.fullstackradio.com/37这将帮助您清楚地理解。

尝试将代码分成小块,然后分别测试每个块。您对一次测试的期望过高。将验证逻辑放在 FormRequest 类中,这会对您有很大帮助。

  • 我会说“永远不要测试你不拥有的东西”。这是一个糟糕的建议。我总是需要一组集成测试来确保我与第三方正确对话。这是一个小型测试套件,因为我总是引入第三方通信的抽象,但它确实存在。然后可以模拟抽象(但不能模拟与第三方的交互)。 (6认同)