ajmcgrail's avatar

ajmcgrail started a new conversation+100 XP

2mos ago

Hello all,

I'm not sure if I'm posting this in the correct place, but I'm looking for the correct way to deal with using factories in phpunit testing in regards to fillables. I'm on Laravel 11. Psuedo MVP below.

For example, let's say I have a Vulnerability model with a belongsTo relationship to an Asset model:

Vulnerability:

  • id
  • description (fillable)
  • asset_id (not nullable)

Asset: -id

If I were to make a factory definition for Vulnerability and I wanted to have an asset automatically be added using factory to a vulnerability, I would think I would follow the documentation and make a definition like:

public function definition(): array
{
	return [
		'description' => $this->faker->paragraph,
		'asset_id' => Asset::factory(),
	]
} 

However this doesn't seem to work with just Vulnerability::factory()->create(), and there'll be an error about a lack of default value for Vulnerability- presumably because asset_id isn't fillable. But I don't want asset_id to be fillable anyway 99% of the time, to prevent users from being able to set it outside of specific routes. In order to follow the method outlined in the documentation, I'd need to add asset_id to the list of fillables, which I'd very much prefer NOT to do. One would think you might be able to work around by doing Vulnerability::unguard() in the given test method where Vulnerability::factory()->create() is used, but as far as I can tell, this also doesn't work and I get the 'does not have default value' error. If the column is not inside of the $fillable array in the model, specifying the factory inside of the definition does not work.

All of the above is irrelevant when doing Vulnerability::factory()->make(), presumably because that never actually persists to the database.

Does anyone have suggestions on how to deal with the issue of fillable + using a factory for a non-fillable column? Any advice is appreciated.

P.S. This is my first post here. If I somehow broke forum etiquette, please let me know.

EDIT: Intermediate update in the event I forget the existence of this thread:

If recycle is used (as in you create an asset by doing $asset = Asset::factory()->create(), and do Vulnerability::factory()->recycle($asset), there's no 'default value missing' error and it all works correctly. It doesn't address the problem regarding creating a default Asset if one wasn't given to the factory, but it's at least a way to partially address the issue.