PHP/Laravel:错误:在 null 上调用成员函数 __call()

问题描述 投票:0回答:1

我目前正在开发一个 Laravel 项目,并且面临着为数据透视表设置工厂的问题。具体来说,我正在尝试为一个表创建一个工厂,作为

Order
Product
模型之间的枢轴。该表名为
order_product
,包含
order_id
product_id
quantity
price
等字段。

测试看起来像这样:

public function testCalculateOrderTotal(): void
    {
        $address = Address::factory()->create();
        $client = Client::factory()->create(['address_id' => $address->id]);
        $order = Order::factory()->create(['client_id' => $client->id]);
        $product1 = Product::factory()->create();
        $product2 = Product::factory()->create();

        $orderProductData1 = [
            'order_id' => $order->id,
            'product_id' => $product1->id,
            'quantity' => 2,
            'price' => 100.00
        ];
        $orderProductData2 = [
            'order_id' => $order->id,
            'product_id' => $product2->id,
            'quantity' => 1,
            'price' => 150.00
        ];

        $orderProduct1 = OrderProduct::factory()->create($orderProductData1);
        $orderProduct2 = OrderProduct::factory()->create($orderProductData2);

        $this->orderProductRepository
            ->shouldReceive('findByOrder')
            ->with($order->id)
            ->once()
            ->andReturn(new Collection([$orderProduct1, $orderProduct2]));

         $expectedTotal = ($orderProductData1['quantity'] * $orderProductData1['price']) +
             ($orderProductData2['quantity'] * $orderProductData2['price']);

         $total = $this->orderProductService->calculateOrderTotal($order->id);

         $this->assertIsFloat($total);
         $this->assertEquals($expectedTotal, $total);
    }

这是我正在尝试测试的服务方法

    public function calculateOrderTotal($order_id): float
    {
        try {
            $orderProducts = $this->orderProductRepository->findByOrder($order_id);
            return $orderProducts->sum(fn($item) => $item->quantity * $item->price);
        } catch (\Throwable $th) {
            throw $th;
        }
    }

当我运行所有测试时(

./vendor/bin/sail exec -T laravel.test ./vendor/bin/phpunit --coverage-html=coverage/
)它不断返回:

 FAILED  Tests\Unit\Services\OrderProductServiceTest > calculate order total                                                                                                                             Error   
  Call to a member function __call() on null

  at tests/Unit/Services/OrderProductServiceTest.php:56
  ➜  56▕ $orderProduct1 = OrderProduct::factory()->create($orderProductData1);
     57▕ $orderProduct2 = OrderProduct::factory()->create($orderProductData2);
     58▕ 

1 个测试/Unit/Services/OrderProductServiceTest.php:56

我的

OrderProductFactory
看起来像这样:

public function definition(): array
{
return [
    'order_id' => Order::factory(),
    'product_id' => Product::factory(),
    'quantity' => $this->faker->numberBetween(1, 10),
    'price' => $this->faker->randomFloat(2, 5, 100),
];
}

我尝试更新我的 OrderProductFactory 但没有成功。

任何帮助或指导将不胜感激!

提前致谢!

php laravel unit-testing phpunit factory
1个回答
0
投票

这看起来并不难。但在帮助您解决这个问题之前,我自己也有几个问题:

  1. 如何实例化该

    $orderProductService
    变量?通过服务容器还是只是新建对象?

  2. 如何在

    $orderProductRepository
    类中实例化
    OrderProductService
    ?是这样的依赖吗?

class OrderProductService
{
    protected $orderProductRepository;

    public function __construct(OrderProductRepository $orderProductRepository)
    {
        $this->orderProductRepository = $orderProductRepository;
    }
}
  1. 我看到你在嘲笑
    OrderProductRepository
    班。阅读[文档][1],必须这样嘲笑:
$this->mock(OrderProductRepository::class, function ($mock) use ($order) {
    $mock->shouldReceive('findByOrder')
        ->with($order->id)
        ->once()
        ->andReturn(new Collection([$orderProduct1, $orderProduct2]));
});

不过,我发现在这种情况下嘲笑是不必要的。该

findByOrder
方法很简单,无论如何都应该返回正确的结果。您只需删除此行即可。

请告诉我们,以便我们帮助您解决。

© www.soinside.com 2019 - 2024. All rights reserved.