PUT request doesn't update nested collection into a test. Works when another request is executed before

171 views Asked by At

PUT request won't update nested collections when the sole test is executed.

  • If I run all the test suite php bin/phpunit, it works.
  • If I make the request via a HTTP client (Postman, cURL...), it works.
  • But if I run this sole test only php bin/phpunit --filter=testEditCategory, it fails. Every other fields (name, description here) are being correctly updated, but not parameters (collection of Parameter).

The same behaviour with a PUT request has been observed with every other nested collections of my application.

Using :

  • Symfony 5.2
  • ApiPlatform 2.5.9
  • Fixtures with hautelook/alice-bundle 2.8

Running test with : php bin/phpunit --filter=testEditCategory

The following test won't pass :

class CategoryTest extends ApiTestCase {

    use RefreshDatabaseTrait;

    public function testEditCategory(): void
    {
        $data = [
            'name' => 'Edited',
            'description' => 'Edited',
            "parameters" => []
        ];

        $response = $this->request(
            'PUT',
            $this->getResourceIri(Category::class, ['name' => 'foobar']),
            $data,
            ['Authorization' => 'Bearer '.self::VALID_JWT]
        );

        $json = json_decode((string)$response->getContent(), true, 512, JSON_THROW_ON_ERROR);
        self::assertEmpty($json['parameters']);
    }

    // ...

Returns :

1) App\Tests\Functional\Api\CategoryTest::testEditCategory
Failed asserting that an array is empty.

But here comes the weird behaviour : when I execute any other HTTP request before, into the test method... The test passes :

// ...
$this->request('GET', 'https://www.google.com');
$response = $this->request(
        'PUT',
        $this->getResourceIri(Category::class, ['name' => 'category_1']),
        $data,
        ['Authorization' => 'Bearer '.self::VALID_JWT]
);
// ...

ApiTestCase.php :

class ApiTestCase extends WebTestCase
{
    protected KernelBrowser $client;

    /** @var string */
    public const VALID_JWT = 'valid_token';

    protected function setUp(): void
    {
        parent::setUp();

        $this->client = static::createClient();
    }

    /**
     * @param string $method
     * @param string $uri
     * @param mixed $content
     * @param array $headers
     * @return Response
     * @throws JsonException
     */
    protected function request(string $method, string $uri, $content = null, array $headers = []): Response
    {
        $server = ['CONTENT_TYPE' => 'application/ld+json', 'HTTP_ACCEPT' => 'application/ld+json'];
        foreach ($headers as $key => $value) {
            if ('content-type' === strtolower($key)) {
                $server['CONTENT_TYPE'] = $value;

                continue;
            }

            $server['HTTP_'.strtoupper(str_replace('-', '_', $key))] = $value;
        }

        if (is_array($content) && false !== preg_match('#^application/(?:.+\+)?json$#', $server['CONTENT_TYPE'])) {
            $content = json_encode($content, JSON_THROW_ON_ERROR);
        }

        $this->client->request($method, $uri, [], [], $server, $content);

        return $this->client->getResponse();
    }
}

Fixtures :

App\Entity\Category:
    category_1:
        name: 'category_1'
        description: 'category 1'


App\Entity\Parameter:
    parameter_1:
        name: 'parameter_1'
        category: '@category_1'
0

There are 0 answers