php 使用assertJsonCount()对Laravel测试中的多个子数组中的项进行计数

fv2wmkja  于 2023-03-28  发布在  PHP
关注(0)|答案(2)|浏览(108)

对于我的产品API的Laravel测试,我试图检查是否为所有产品列出了正确的价格数量。API返回Json,价格是 products..prices* 数组中的项目。
我是Laravel测试的新手。
我如何循环浏览所有产品并查看它们的价格?

$response = $this->getJson('/api/product/');

$json_array = $response->json();
$test_passed = true;

for ($i = 0; $i < count($json_array); $i++) {
  //for simplification I check here if all the products have 2 prices
  $test_passed = $response->assertJsonCount(2, "product.$i.prices");
}

//check if all the test passed
$this->assertTrue($passed_test);

这工作正常,但它用完内存真的很快。我做错了什么?

更新日期:

我在Laravel API中发现AssertableJson有and -〉each()方法。

$response->assertJson(fn (AssertableJson $json) =>
  $json->each(fn (AssertableJson $json) =>
    //2 will be dynamic in the final implementation.
    $json->has('prices', 2) 
    )
  );

这不起作用,显然......我不能弄清楚this -〉each()是如何工作的,并且在网上找不到示例。我能找到的只是Laravel文档,但他们没有给予嵌套数组的示例。

c9x0cxw0

c9x0cxw01#

既然你应该为每一个测试擦干净你的数据库,以一个干净的石板开始,我认为采取的步骤是
1.创建任意数量的Product模型以及与之关联的任意数量的Price模型
1.调用API端点
1.AssertProduct模型的数量与我们在第1步中指定的一样多。
1.Assert每个Product具有与我们在步骤1中指定的数量相同的Price模型。

public function test_products_api_returns_correct_amount_of_products()
{
    // ARRANGE
    Product::factory()->count(15)->create()

    // ACT
    $response = $this->getJson('/api/product/');

    // ASSERT
    $response->assertJsonCount(15, 'products');
}

public function test_products_api_returns_correct_amount_of_prices_for_each_product()
{
    // ARRANGE
    $counts = [1, 3, 5, 7, 10];
    foreach ($counts as $count) {
        Product::factory()
            ->has(Price::factory()->count($count)) // or ->hasPrices($count)
            ->create();
    }

    // ACT
    $response = $this->getJson('/api/product/');

    // ASSERT
    foreach ($counts as $index => $count) {
        $response->assertJsonCount($count, "products.$index.prices");
    }
}

注意这里我在foreach中使用了数组的key值。这在AssertableJson语法中是不可能的,因为Closure不接受第二个参数(不像Collectioneach方法,如果我想使用$collection->each(function ($item, $key) { ... });,我可以使用键。
AssertableJson API有一些限制,因此您不能将其真正用于此测试,除非您制作单一类型的产品。

public function test_products_api_returns_correct_amount_of_prices_for_each_product()
{
    // ARRANGE
    Product::factory()
        ->count(15)
        ->has(Price::factory()->count(5))
        ->create();
    }

    // ACT
    $response = $this->getJson('/api/product/');

    // ASSERT
    $response->assertJson(fn (AssertableJson $json) =>
        $json->has('products', 15, fn (AssertableJson $product) =>
            $product->count('prices', 5)->etc()
        ) 
    );
    // or
    $response->assertJson(fn (AssertableJson $json) =>
        $json->has('products', 15, fn (AssertableJson $product) =>
            $product->has('prices', 5, fn (AssertableJson $price) => 
                // assertions about the products.*.prices.* array.
            )->etc()
        ) 
    );
}

您可以创建的另一个测试是针对返回的json结构的测试,这对jsonapi很重要。

public function test_products_api_returns_the_correct_structure()
{
    // ARRANGE
    ... make all the product, prices, options, etc

    // ACT
    $response = $this->getJson('/api/product/');

    // ASSERT
    $response->assertJsonStructure([
        'products' => [
            '*' => [
                'product_id',
                'name',
                'description',
                'included',
                'is_active',
                'prices' => [
                    '*' => [
                        'price_id',
                        'weight',
                        'height',
                        'length',
                        'depth',
                        'pieces',
                        'color',
                        'price',
                        'start_time',
                        'end_time',
                        'sales' => [
                            '*' => [
                                'sale_id',
                                'sale_price',
                                'sale_start_time',
                                'sale_end_time',
                            ],
                        ],
                    ],
                ],
                'photos' => [
                    '*' => [
                        'photo_id',
                        'alt',
                        'path',
                    ],
                ],
                'properties' => [
                    '*' => [
                        'property_id',
                        'name',
                        'description',
                        'quantitative',
                        'position',
                        'is_active',
                        'properties_properties' => [
                            '*' => [
                                'properties_property_id',
                                'name',
                                'icon',
                                'path',
                                'attributes' => [
                                    '*' => [
                                        'product_id',
                                        'properties_property_id',
                                        'position',
                                        'highlight',
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
                'options' => [
                    '*' => [
                        'option_id',
                        'name',
                        'place_holder',
                        'position',
                        'is_active',
                        'options_options' => [
                            '*' => [
                                'options_option_id',
                                'name',
                                'position',
                                'price',
                                'is_active',
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ]);
}

我用你发布的json(jsonblob.com/1087309750307405824)测试了最后一个,它通过了。

lmvvr0a8

lmvvr0a82#

基于你在这里发布的JSON:https://jsonblob.com/1087309750307405824一些小的改变可以解决你的问题

$response = $this->getJson('/api/product/');
$test_passed = true;

for ($i = 0; $i < count($response->json("products")); $i++) {
  //for simplification I check here if all the products have 2 prices
  $test_passed = $response->assertJsonCount(2, "products.$i.prices");
}

//check if all the test passed
$this->assertTrue($passed_test);

如果你的代码内存不足,可能是你的数据库中的所有产品和产品JSON大小太大,或者可能是你的系统内存限制。
要检查php内存使用情况,可以在“for循环”中使用memory_get_usage函数

相关问题