iT邦幫忙

2019 iT 邦幫忙鐵人賽

1

TestResponse 是一個輔助測試 response 用的物件,它內建混入(mixin)了 Response 物件功能:

use Macroable {
    __call as macroCall;
}

public function __call($method, $args)
{
    // 實作了 Macroable 的功能
    if (static::hasMacro($method)) {
        return $this->macroCall($method, $args);
    }

    // 混入 Response
    return $this->baseResponse->{$method}(...$args);
}

// 包括屬性也都能取得,不過只能取得 public 屬性
public function __get($key)
{
    return $this->baseResponse->{$key};
}

並提供了許多 assert 方法,如 assertSuccessful()

public function assertSuccessful()
{
    PHPUnit::assertTrue(
        $this->isSuccessful(),
        'Response status code ['.$this->getStatusCode().'] is not a successful status code.'
    );

    return $this;
}

這讓測試程式碼變得更加容易理解。


大部分的 assert 方法都是很單純的包裝 Response 的結果,少部分比較特別的如 View:

// assert view 的名稱
public function assertViewIs($value)
{
    // 確定 Response 是 View
    $this->ensureResponseHasView();

    PHPUnit::assertEquals($value, $this->original->getName());

    return $this;
}

protected function ensureResponseHasView()
{
    // 透過 __get 取得 original,並確認它是 View
    if (! isset($this->original) || ! $this->original instanceof View) {
        return PHPUnit::fail('The response is not a view.');
    }

    return $this;
}

JSON 的 assert 設計也是非常厲害,如看是否有 JSON 片段 assertJsonFragment()

public function assertJsonFragment(array $data)
{
    // 將 response json 排序並 encode 回字串
    $actual = json_encode(Arr::sortRecursive(
        (array) $this->decodeResponseJson()
    ));

    // 依續把傳入的 data 做比對
    foreach (Arr::sortRecursive($data) as $key => $value) {
        // 產生預期的字串組
        $expected = $this->jsonSearchStrings($key, $value);

        // 如果有找到就是有
        PHPUnit::assertTrue(
            Str::contains($actual, $expected),
            'Unable to find JSON fragment: '.PHP_EOL.PHP_EOL.
            '['.json_encode([$key => $value]).']'.PHP_EOL.PHP_EOL.
            'within'.PHP_EOL.PHP_EOL.
            "[{$actual}]."
        );
    }

    return $this;
}

protected function jsonSearchStrings($key, $value)
{
    // 假設是 'a' 與 1 ,則會產生字串 `"a":1` 
    $needle = substr(json_encode([$key => $value]), 1, -1);

    return [
        $needle.']', // `"a":1]`
        $needle.'}', // `"a":1}`
        $needle.',', // `"a":1,`
    ];
}

上一篇
分析 Laravel Feature Test
系列文
Laravel 原始碼分析46

尚未有邦友留言

立即登入留言