Abzor's avatar
Level 5

Unit test assertDatabaseHas fails because of unescaped json

Hi all,

I'm using the Spatie package Laravel-translatable. A translatable title is stored in the database as following:

{"en": "Eveniet aperiam totam placeat qui nihil sit et.","nl": "Eveniet aperiam totam placeat qui nihil sit et."}

The unit test fails with this message:

Failed asserting that a row in the table [posts] matches the attributes {
    "title": {
        "en": "Eveniet aperiam totam placeat qui nihil sit et.",
        "nl": "Eveniet aperiam totam placeat qui nihil sit et."
    }
}.

Found: [
    {
        "title": "{\"en\":\"Eveniet aperiam totam placeat qui nihil sit et.\",\"nl\":\"Eveniet aperiam totam placeat qui nihil sit et.\"}"
    }
].

Does anyone know how I can solve this? The data is only unescaped during a test.

0 likes
2 replies
LaryAI's avatar
Level 58

When using Laravel's assertDatabaseHas method in a unit test, it's important to match the exact format of the data as it is stored in the database. Since the title field is stored as a JSON string in the database, you should assert against the JSON string rather than an array or object.

Here's how you can modify your test to correctly assert the presence of the JSON string in the database:

public function testDatabaseHasJsonTitle()
{
    // Assuming you have a Post model and you've already created a post with the given title
    // ...

    $titleJson = json_encode([
        "en" => "Eveniet aperiam totam placeat qui nihil sit et.",
        "nl" => "Eveniet aperiam totam placeat qui nihil sit et."
    ]);

    $this->assertDatabaseHas('posts', [
        'title' => $titleJson
    ]);
}

In this example, we're using json_encode to convert the array to a JSON string that matches the format stored in the database. This should allow your test to pass, assuming that the rest of the test setup is correct and the post with the specified title exists in the database.

domioanna's avatar

Are you able to share the code from your test?

Please or to participate in this conversation.