The same problem, but i resolved it another way
$userSettings = UserSettings::find(1);
$this->assertEquals(['foo' => 'bar'], $userSettings->settings);
Within my PHPUnit test I'm trying to assert that an API endpoint properly stores the data sent to it. In my database I have a field called settings which stores data using the type: JSON. Everything works just fine. I just can't get PHPUnit to accept the assertion, despite the values visually appearing the same.
I'm using PHPUnit version 5.7.
$data = [
'user_id' => 1,
'settings' => '{"foo": "bar"}'
];
$this->post('user_settings', $data);
$this->assertDatabaseHas('user_settings', [
'id' => 1,
'user_id' => 1,
'settings' => '{"foo": "bar"}'
]);
Failed asserting that a row in the table [user_settings] matches the attributes {
"id": 1,
"settings": "{\"foo\": \"bar\"}"
}.
Found: [
{
"id": 1,
"user_id": 1,
"settings": "{\"foo\": \"bar\"}",
"created_at": "2017-07-22 17:04:35",
"updated_at": "2017-07-22 17:04:35",
"deleted_at": null
}
].
Any ideas why this would fail? Does PHPUnit just not like JSON database fields?
You have to first cast the value to JSON to be able to search for it in MySQL. I use the following helper method to do this:
/**
* Generate a raw DB query to search for a JSON field.
*
* @param array|json $json
*
* @throws \Exception
*
* @return \Illuminate\Database\Query\Builder
*/
function castToJson($json)
{
// Convert from array to json and add slashes, if necessary.
if (is_array($json)) {
$json = addslashes(json_encode($json));
}
// Or check if the value is malformed.
elseif (is_null($json) || is_null(json_decode($json))) {
throw new \Exception('A valid JSON string was not provided.');
}
return \DB::raw("CAST('{$json}' AS JSON)");
}
So, using my original example the database assertion would become:
$this->assertDatabaseHas('user_settings', [
'id' => 1,
'user_id' => 1,
'settings' => castToJson('{"foo": "bar"}'),
]);
Hope that helps!
Please or to participate in this conversation.