Получение «Попытка получить свойство« промежуточный итог »необъекта» при использовании findOrFail - PullRequest
0 голосов
/ 26 января 2020

У меня есть следующий фрагмент кода в сервисе:

public function add(array $data) : Order
    {
        // retrieve item data
        $item       = MenuItem::findOrFail($data[OrderItem::ORDER_ITEM_ITEM_ID]);
        $quantity   = $data[OrderItem::ORDER_ITEM_QUANTITY];
        $order_no   = $data[Order::ORDER_NO] ?? null;
        $session_id = $data[Order::ORDER_SESSION_ID];

        $order = $order_no ? Order::findOrFail($order_no) : $this->createOrder([Order::ORDER_SESSION_ID => $session_id]);

        $order_item = $this->order_item->createOrderItem($order->order_no, $item, $quantity);

        // update order total
        $order->subtotal += $order_item->subtotal;
        $order->total    += $order_item->subtotal;
        $order->update();

        return $order;
    }

При выполнении теста я получаю:

Получение "Попытка получить свойство" промежуточный итог 'необъекта "

Найденный объект не пустой, иначе он не состоялся бы. Но ни промежуточный, ни общий не принадлежат объекту. Если я печатаю объект, я получаю другие поля, кроме этих двух. Они оба находятся в моем $fillable массиве, и я определил ->default(0); в моей миграции.

Что происходит?

РЕДАКТИРОВАТЬ

PHP Выход блока ниже:

PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

array:5 [
  "message" => "Trying to get property 'subtotal' of non-object"
  "exception" => "ErrorException"
  "file" => "/Users/bigweld/Sites/restaurantbe/app/Services/OrderService.php"
  "line" => 110
  "trace" => array:33 [
    0 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/app/Services/OrderService.php"
      "line" => 110
      "function" => "handleError"
      "class" => "Illuminate\Foundation\Bootstrap\HandleExceptions"
      "type" => "->"
    ]
    1 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/app/Http/Controllers/API/OrderController.php"
      "line" => 57
      "function" => "add"
      "class" => "App\Services\OrderService"
      "type" => "->"
    ]
    2 => array:3 [
      "function" => "add"
      "class" => "App\Http\Controllers\API\OrderController"
      "type" => "->"
    ]
    3 => array:3 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Controller.php"
      "line" => 54
      "function" => "call_user_func_array"
    ]
    4 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php"
      "line" => 45
      "function" => "callAction"
      "class" => "Illuminate\Routing\Controller"
      "type" => "->"
    ]
    5 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Route.php"
      "line" => 219
      "function" => "dispatch"
      "class" => "Illuminate\Routing\ControllerDispatcher"
      "type" => "->"
    ]
    6 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Route.php"
      "line" => 176
      "function" => "runController"
      "class" => "Illuminate\Routing\Route"
      "type" => "->"
    ]
    7 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 681
      "function" => "run"
      "class" => "Illuminate\Routing\Route"
      "type" => "->"
    ]
    8 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 130
      "function" => "Illuminate\Routing\{closure}"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    9 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 105
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    10 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 683
      "function" => "then"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    11 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 658
      "function" => "runRouteWithinStack"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    12 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 624
      "function" => "runRoute"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    13 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Routing/Router.php"
      "line" => 613
      "function" => "dispatchToRoute"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    14 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 177
      "function" => "dispatch"
      "class" => "Illuminate\Routing\Router"
      "type" => "->"
    ]
    15 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 130
      "function" => "Illuminate\Foundation\Http\{closure}"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    16 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php"
      "line" => 105
      "function" => "Illuminate\Pipeline\{closure}"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    17 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 152
      "function" => "then"
      "class" => "Illuminate\Pipeline\Pipeline"
      "type" => "->"
    ]
    18 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php"
      "line" => 117
      "function" => "sendRequestThroughRouter"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    19 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php"
      "line" => 434
      "function" => "handle"
      "class" => "Illuminate\Foundation\Http\Kernel"
      "type" => "->"
    ]
    20 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php"
      "line" => 406
      "function" => "call"
      "class" => "Illuminate\Foundation\Testing\TestCase"
      "type" => "->"
    ]
    21 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/tests/Feature/OrdersTest.php"
      "line" => 428
      "function" => "json"
      "class" => "Illuminate\Foundation\Testing\TestCase"
      "type" => "->"
    ]
    22 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 1408
      "function" => "when_adding_the_same_item_twice_to_an_empty_order_then_only_one_order_item_is_created_but_its_quantity_increases"
      "class" => "Tests\Feature\OrdersTest"
      "type" => "->"
    ]
    23 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 1028
      "function" => "runTest"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    24 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestResult.php"
      "line" => 691
      "function" => "runBare"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    25 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestCase.php"
      "line" => 756
      "function" => "run"
      "class" => "PHPUnit\Framework\TestResult"
      "type" => "->"
    ]
    26 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 597
      "function" => "run"
      "class" => "PHPUnit\Framework\TestCase"
      "type" => "->"
    ]
    27 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 597
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    28 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/Framework/TestSuite.php"
      "line" => 597
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    29 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/TextUI/TestRunner.php"
      "line" => 621
      "function" => "run"
      "class" => "PHPUnit\Framework\TestSuite"
      "type" => "->"
    ]
    30 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/TextUI/Command.php"
      "line" => 200
      "function" => "doRun"
      "class" => "PHPUnit\TextUI\TestRunner"
      "type" => "->"
    ]
    31 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/src/TextUI/Command.php"
      "line" => 159
      "function" => "run"
      "class" => "PHPUnit\TextUI\Command"
      "type" => "->"
    ]
    32 => array:5 [
      "file" => "/Users/bigweld/Sites/restaurantbe/vendor/phpunit/phpunit/phpunit"
      "line" => 61
      "function" => "main"
      "class" => "PHPUnit\TextUI\Command"
      "type" => "::"
    ]
  ]
]

1 Ответ

1 голос
/ 26 января 2020

Согласно нашему разговору в комментариях, одна из проблем, с которыми вы сталкиваетесь в своей функции и, как следствие, вызывает проблему в вашем тесте, - это зависимость, при которой результат не может быть гарантирован каждый раз. То есть ваш звонок в другую службу в вашей функции add не гарантирован , чтобы обеспечить определенный c вывод.

Думайте о своем тесте так.

  • Я начинаю с заказа с нулевым товаром и нулевой промежуточной суммой
  • Я хочу добавить товар к этому заказу
  • Я хочу завершить заказ с одним товаром, и подытог в десять долларов

В этом тесте вас не волнует как создается элемент заказа, вам просто нужно, чтобы он создавался с заданное значение c, чтобы при его добавлении к вашему заказу конечный результат соответствовал ожидаемому.

В этом случае вы хотите, чтобы $this->order_item был поддельным объектом, и тогда вы можете смоделировать вызов createOrderItem, чтобы вернуть известный объект заказа. Немного сложно показать вам законченное решение, поскольку оно может включать некоторые архитектурные изменения, но ваш тест будет выглядеть примерно так:

public function it_adds_an_item_to_an_order()
{
  $orderItem = Mock(OrderItem::class); // Use whatever mocking lib is available
  $orderitem->shouldReceive('createOrderItem').andReturn(new OrderItem([$subtotal=>10.00]));
  $orderService = new OrderService($orderItem);

  $order = $orderService->add($data);

  $this->assertNotNull($order);
  $this->assertEquals(10.00, $order->subtotal);
}

Надеюсь, это поможет вам в будущем.

...