Last active
October 2, 2023 22:50
-
-
Save Oldenborg/dbea4eb6df6cabf388310e6b0168262f to your computer and use it in GitHub Desktop.
Laravel test trait: assert JSON exact
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Tests\Traits; | |
use Illuminate\Testing\TestResponse; | |
use Illuminate\Support\Arr; | |
use PHPUnit\Framework\Assert as PHPUnit; | |
trait AssertJson | |
{ | |
/* @before */ | |
public function setUp(): void | |
{ | |
parent::setUp(); | |
$this->setUpAssertJson(); | |
} | |
public function setUpAssertJson(): void | |
{ | |
TestResponse::macro('assertJsonStructureExact', function (array $structure = null, $responseData = null) { | |
$transformStructure = function ($structure, $prefix = '') use (&$transformStructure) { | |
$result = []; | |
foreach ($structure as $key => $value) { | |
if (is_array($value) && array_keys($value) !== range(0, count($value) - 1)) { | |
$result = array_merge($result, $transformStructure($value, $prefix . $key . '.')); | |
} elseif (is_array($value)) { | |
foreach ($value as $k) { | |
$result[] = $prefix . $key . '.' . $k; | |
} | |
} else { | |
$result[] = $prefix . $value; | |
} | |
} | |
return $result; | |
}; | |
$expectedKeys = $transformStructure($structure); | |
sort($expectedKeys); | |
if ($responseData === null) { | |
$responseData = json_decode($this->getContent(), true); | |
} | |
$responseKeys = Arr::dot($responseData); | |
$responseKeys = array_keys($responseKeys); | |
sort($responseKeys); | |
$missingKeys = array_diff($expectedKeys, $responseKeys); | |
$extraKeys = array_diff($responseKeys, $expectedKeys); | |
$errorMessage = ""; | |
if (!empty($extraKeys)) { | |
$prettyList = "[\n '" . implode("',\n '", $extraKeys) . "'\n]"; | |
$errorMessage .= "The response had the following unexpected parameters:\n" . $prettyList . "."; | |
} | |
if (!empty($missingKeys)) { | |
$prettyList = "[\n '" . implode("',\n '", $missingKeys) . "'\n]"; | |
$errorMessage .= "The response is missing the following parameters:\n" . $prettyList . "."; | |
} | |
PHPUnit::assertTrue(empty($missingKeys) && empty($extraKeys), $errorMessage); | |
return $this; | |
}); | |
} | |
} |
I had success fixing it by doing this, instead of calling json_decode()
:
$responseData = $this->decodeResponseJson()->json();
Not sure when exactly the json()
method was introduced.
I had success fixing it by doing this, instead of calling
json_decode()
:$responseData = $this->decodeResponseJson()->json();
Not sure when exactly the
json()
method was introduced.
I havent look at this trait for a long time. And I haven't been doing much Laravel development the past few years. @IllyaMoskvin do you suggest I update my Trait to reflect this change to $responseData = $this->decodeResponseJson()->json();
?
I have finally taken the time to update this Trait so it works with the lastest version of Laravel (10)
At the same time, I have implemented more meaningful error messages that will be visible in the console.
FAILED Tests\Feature\AuthenticationTest > a guest can register
The response had the following unexpected parameters:
[
'data.token',
'data.user.created_at',
'data.user.email_verification_token',
'data.user.updated_at'
],
The response is missing the following parameters:
[
'status'
].
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
After upgrading to Laravel 8, I got this error from previously (in Laravel 7) working tests.
The breaking change is in:
decodeResponseJson()
will now return an object with the original json and the decoded array. Unfortunately, the decoded array is protected and not accessible from this trait.Here is how to fix this: (Line 25-27)