Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Lucky you! You found an early release chapter - it will be fully polished and published shortly!

JSON Test Assertions & Seeding the Database

This Chapter isn't
quite ready...

Rest assured, the gnomes are hard at work
completing this video!

Browse Tutorials

Let's make this test real with data and assertions.

There are two main ways to do assertions with Browser. First, it comes with a bunch of built-in methods to help, like ->assertJson(). Or... you can always just grab the JSON that comes back from an endpoint and check things using the built-in PHPUnit assertions you know and love. We'll see both.

Let's start by checking ->assertJson(). When we run that:

symfony php bin/phpunit

It passes! Cool! We know that this response should have a hydra:totalItems property set to the number of results. Right now, our database is empty... but we can at least assert that it matches zero.

To do that, use ->assertJsonMatches(). This is a special method from Browser that uses a special syntax that allows us to read different parts off the JSON. We'll dig into it in a minute.

But this one is simple: assert that hydra:totalItems equals 0.

When we try this:

symfony php bin/phpunit

It fails! But with a great error:

mtdowling/jmespath.php is required to search JSON

Hello JMESPath

Ah, we need to install that! Copy the composer require line, find your terminal, and run it:

composer require mtdowling/jmespath.php --dev

This "JMESPath" thing is actually super cool: it's a "query language" for reading different parts of any JSON. For example, if this is your JSON and you want to read the a key, just say a. Simple.

But you can also do deeper, like: a.b.c.d. Or, get crazier: grab the 1 index, or grab a.b.c, then the 0 index, .d, the 1 index then the 0 index. You can even slice the array in different ways. Basically... you can go nuts.

But we're not going to lose our minds with this. It's a handy syntax... but if things get too complex, we can always test the JSON manually, which we'll do in a bit.

Anyway, now that we have the library installed, let's run the test again.

symfony php bin/phpunit

It still fails! With a weird error:

Syntax error at character 5 hydra:totalItems.

Unfortunately, the : is a special character inside of JMESPath. So whenever we have a :, we need to put quotes around that key.

Not ideal, but not a huge inconvenience.

Now when we try it:

symfony php bin/phpunit

It passes!

Seeding the Database

But... this isn't a very interesting test: we're just asserting that we get nothing back... because the database is empty. To make our test real, we need data: we need to seed the database with data at the start of the test.

Fortunately, Foundry makes that dead-simple. At the top, call DragonTreasureFactory::createMany() and let's create 5 treasures. Now, below, assert that we get 5 results. It's just that simple. And actually, let me put our dump back so we can see the result.

Try it now:

symfony php bin/phpunit

It passes! And if you look up, yea! The response has 5 treasures! Dang, that was easy.

Next: let's use JMESPath to assert something more challenging. Then we'll back up and see how we can dig into Browser to give us infinite flexibility - and simplicity - when it comes to testing JSON.

Leave a comment!

Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=8.1",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "api-platform/core": "^3.0", // v3.1.2
        "doctrine/annotations": "^2.0", // 2.0.1
        "doctrine/doctrine-bundle": "^2.8", // 2.8.3
        "doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.2
        "doctrine/orm": "^2.14", // 2.14.1
        "nelmio/cors-bundle": "^2.2", // 2.2.0
        "nesbot/carbon": "^2.64", // 2.66.0
        "phpdocumentor/reflection-docblock": "^5.3", // 5.3.0
        "phpstan/phpdoc-parser": "^1.15", // 1.16.1
        "symfony/asset": "6.2.*", // v6.2.5
        "symfony/console": "6.2.*", // v6.2.5
        "symfony/dotenv": "6.2.*", // v6.2.5
        "symfony/expression-language": "6.2.*", // v6.2.5
        "symfony/flex": "^2", // v2.2.4
        "symfony/framework-bundle": "6.2.*", // v6.2.5
        "symfony/property-access": "6.2.*", // v6.2.5
        "symfony/property-info": "6.2.*", // v6.2.5
        "symfony/runtime": "6.2.*", // v6.2.5
        "symfony/security-bundle": "6.2.*", // v6.2.6
        "symfony/serializer": "6.2.*", // v6.2.5
        "symfony/twig-bundle": "6.2.*", // v6.2.5
        "symfony/ux-react": "^2.6", // v2.7.1
        "symfony/ux-vue": "^2.7", // v2.7.1
        "symfony/validator": "6.2.*", // v6.2.5
        "symfony/webpack-encore-bundle": "^1.16", // v1.16.1
        "symfony/yaml": "6.2.*" // v6.2.5
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.2
        "mtdowling/jmespath.php": "^2.6", // 2.6.1
        "phpunit/phpunit": "^9.5", // 9.6.3
        "symfony/browser-kit": "6.2.*", // v6.2.5
        "symfony/css-selector": "6.2.*", // v6.2.5
        "symfony/debug-bundle": "6.2.*", // v6.2.5
        "symfony/maker-bundle": "^1.48", // v1.48.0
        "symfony/monolog-bundle": "^3.0", // v3.8.0
        "symfony/phpunit-bridge": "^6.2", // v6.2.5
        "symfony/stopwatch": "6.2.*", // v6.2.5
        "symfony/web-profiler-bundle": "6.2.*", // v6.2.5
        "zenstruck/browser": "^1.2", // v1.2.0
        "zenstruck/foundry": "^1.26" // v1.28.0