logo
podcast Podcast
get help Get Unstuck

Why isn't my JSON column default value working in tests?

And how to fix it

Joel Clermont
Joel Clermont
2025-08-19

I have a model with a JSON column which gets cast to a Collection by Eloquent.

To keep application logic simple, I don't want to allow null values in this column. Instead, I want to ensure that the column defaults to an empty array when no value is provided.

This is easy with the following bit of migration code:

$table->json('example_field')->default(new Expression('(JSON_ARRAY())'));

One slight issue with this approach shows up while writing tests.

If I use a factory to create an instance of this model, that field will not yet be set to the default in my new instance:

$model = Model::factory()->create();
$model->example_field; // null

This is because the default value is applied at the database level, and the model was created in-memory, persisted to the database, but not read back from the database.

One solution would be to add this field to my factory definition with an empty array, but that would have meant duplicating the default value in two places, which I don't like.

Instead, I solved this issue by calling $model->refresh() to read the model back from the database right after the factory call as part of my test data setup. Yes, this introduces an extra database query, but the marginal performance hit in some tests is worth it to me to keep my code clean.

And because this is not a normal thing to do, I added a comment to my test code to explain why this is necessary.

Here to help,

Joel

P.S. The next time you're struggling with a problem, don't forget that the community and Get Unstuck sessions are here to help you out.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.