Ссылки на дочерние объекты не возвращаются в ApiTestCase, но работают в других местах. - PullRequest
1 голос
/ 12 марта 2020

У меня есть две сущности: клиент (отсканированы методы доступа)

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ApiResource(
 *     collectionOperations={
 *         "get"={"normalization_context"={"groups"="client:list"}},
 *         "post"
 *     },
 *     itemOperations={
 *         "get"={"normalization_context"={"groups"="client:item"}},
 *     },
 *     paginationEnabled=false,
 *     order={"name"="ASC"}
 * )
 * @ORM\Entity(repositoryClass="App\Repository\ClientRepository")
 */
class Client
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups({"client:list", "client:item"})
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank
     * @Groups({"client:list", "client:item"})
     */
    private $name;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Package", mappedBy="client")
     * @Groups({"client:item"})
     */
    private $packages;

    public function __construct()
    {
        $this->packages = new ArrayCollection();
    }

и пакет:

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(
 *     collectionOperations={
 *         "get"={"normalization_context"={"groups"="package:list"}},
 *         "post"={"denormalization_context"={"groups"="package:list"}},
 *     },
 *     itemOperations={
 *         "get"={"normalization_context"={"groups"="package:item"}},
 *         "delete",
 *     },
 *
 * )
 * @ApiFilter(SearchFilter::class, properties={"client": "exact"})
 * @ORM\Entity(repositoryClass="App\Repository\PackageRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class Package
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     * @Groups({"package:list", "package:item"})
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Groups({"package:list", "package:item"})
     */
    private $name;

    /**
     * @ORM\Column(type="datetime")
     * @Groups({"package:item"})
     */
    private $createdAt;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Client", inversedBy="packages")
     * @ORM\JoinColumn(nullable=false)
     * @Groups({"package:list", "package:item"})
     */
    private $client;

    /**
     * @ORM\Column(type="string", length=64)
     */
    private $status;

Когда я просматриваю браузер API (или использую cURL в кли) и запросить одного клиента, я вижу, что дочерние объекты пакета возвращаются в ответе (запрашивается как JSON только для того, чтобы сделать данные более понятными):

{
  "id": 1,
  "name": "First Client",
  "packages": [
    "/api/packages/1",
    "/api/packages/2"
  ]
}

Однако в моем тестовом случае дочерний объект сущности не возвращаются. Мой тест выглядит следующим образом:

    public function testItShouldReturnASpecificClient(): void
    {
        $client = static::createClient();
        $response = $client->request('GET', '/api/clients/1', ['headers' => ['Accept' => 'application/json']]);
        $data = json_decode($response->getContent(), false);

        static::assertSame(1, $data->id);
        static::assertCount(2, $data->packages);
    }

И второе утверждение не выполняется. Когда я выкидываю ответ, я вижу, что свойство пакетов не заполнено:

class stdClass#1937 (3) {
  public $id =>
  int(1)
  public $name =>
  string(12) "First Client"
  public $packages =>
  array(0) {
  }
}

Чего мне здесь не хватает, чтобы заставить его вести себя как API вне теста?

1 Ответ

0 голосов
/ 18 марта 2020

Проблема была с моими приборами все время, спасибо @ihsan за руководство в моей отладке.

Ранее я предполагал, что все, что мне нужно было сделать, это ссылка на клиента в пакете:

App\Entity\Package:
  package_1:
    name: 'Inactive Package For First Client'
    createdAt: <dateTime('today -1 year')>
    status: 'INACTIVE'
    client: '@client_1'
  package_2:
    name: 'Active Package For First Client'
    createdAt: <dateTime('today -1 week')>
    status: 'ACTIVE'
    client: '@client_1'

Однако для правильной работы тестов мне пришлось также связать пакеты с клиентом:

App\Entity\Client:
  client_1:
    name: First Client
    packages:
      - '@package_1'
      - '@package_2'
...