Laravel系列。有某种断言结构方法吗?

时间:2017-11-02 07:38:28

标签: php laravel phpunit laravel-5.5 laravel-collection

我正在编写测试,我想断言,返回的集合有一些特定的结构。

要在json对象上使用assertJsonStructure()方法声明Responce我。

我找不到\Illuminate\Support\Collection的相似内容。我是否错过了一些包/框架方法。

我想要的一个例子

$collection = collect([
    'name'      => 'John',
    'surname'   => 'Smith',
    'birthoday' => [
        'day'   => 23,
        'month' => 5,
        'year'  => 1970,
    ],
]);

$collection->assertStructure([          //true
    'name',
    'surname',
    'birthday' => ['day', 'month', 'year'],
]);

我会接受

  

没有

作为答案,但如果它是一个如何验证这样的嵌套集合的例子。

2 个答案:

答案 0 :(得分:3)

Collection实例上没有这样的功能,你可以做的最接近的是:

  • 检查是否有has()
  • 的密钥
  • 检查它是否包含contains()
  • 的某个值
  • 还有其他方法可以检查是否存在某些内容,但

如果您需要灵感,可以使用Laravel在assertJsonStructure()中实施/Illuminate/Foundation/Testing/TestResponse.php的方式来获取灵感:

/**
 * Assert that the response has a given JSON structure.
 *
 * @param  array|null  $structure
 * @param  array|null  $responseData
 * @return $this
 */
public function assertJsonStructure(array $structure = null, $responseData = null)
{
    if (is_null($structure)) {
        return $this->assertJson($this->json());
    }

    if (is_null($responseData)) {
        $responseData = $this->decodeResponseJson();
    }

    foreach ($structure as $key => $value) {
        if (is_array($value) && $key === '*') {
            PHPUnit::assertInternalType('array', $responseData);

            foreach ($responseData as $responseDataItem) {
                $this->assertJsonStructure($structure['*'], $responseDataItem);
            }
        } elseif (is_array($value)) {
            PHPUnit::assertArrayHasKey($key, $responseData);

            $this->assertJsonStructure($structure[$key], $responseData[$key]);
        } else {
            PHPUnit::assertArrayHasKey($value, $responseData);
        }
    }

    return $this;
}

正如您所看到的,在存在子结构的情况下,会有一个递归调用来检查结构。

<强>更新

作为解决问题的基本测试,我将assertJsonStructure()修改为assertArrayStructure()并进行了此工作测试:

/**
 * A basic test example.
 *
 * @return void
 */
public function testBasicTest()
{
    $collect = collect(['name' => '1', 'detail' => ['age' => 1,'class' => 'abc']]);

    $this->assertArrayStructure(['name', 'detail' => ['class', 'age']], $collect->toArray());
}


/**
 * Assert the array has a given structure.
 *
 * @param  array  $structure
 * @param  array  $arrayData
 * @return $this
 */
public function assertArrayStructure(array $structure, array $arrayData)
{
    foreach ($structure as $key => $value) {
        if (is_array($value) && $key === '*') {
            $this->assertInternalType('array', $arrayData);

            foreach ($arrayData as $arrayDataItem) {
                $this->assertArrayStructure($structure['*'], $arrayDataItem);
            }
        } elseif (is_array($value)) {
            $this->assertArrayHasKey($key, $arrayData);

            $this->assertArrayStructure($structure[$key], $arrayData[$key]);
        } else {
            $this->assertArrayHasKey($value, $arrayData);
        }
    }

    return $this;
}

答案 1 :(得分:1)

答案是没有,你可以简单地在API documentation查找断言的laravel方法,命名空间Illuminate\Support\Collection上没有任何方法可以找到你要找的东西。 (你可以找到Laravel断言方法here

作为一种可行的替代方案,为什么不只是序列化您的集合并使用assertJsonStructure()方法进行检查?

您可以使用response()帮助程序填充Illuminate/Foundation/Testing/TestResponse

use Illuminate/Foundation/Testing/TestResponse;

$testResponse = new TestResponse(response()->json($collection->toArray());
return $testResponse->assertJsonStructure([
    'name',
    'surname',
    'birthday' => ['day', 'month', 'year'],
]);

我是如何找到这个解决方案的:

  • 您需要在测试中返回方法$this->json()的完全相同的对象,该对象来自特征MakesHttpRequestshere
  • 正如方法注释指定的那样,它返回Illuminate\Foundation\Testing\TestResponse
  • 查找构造函数at the docs并查看它需要什么,一般响应对象Illuminate/Http/Response

希望这会对你有所帮助。