Reputation: 2485
If we had the below code that we wanted to test, what would be the best way to simulate a failed save? At the moment the only part I am missing from my test is the else
statement.
The save is part of a loop, where we take $customers
loop through them and perform some actions.
$customers = Customer::where('created_at', '<=', $start);
$customers->each(function ($customer, $key) {
if ($customer->save()) {
//Do something here
} else {
//Saving failed, log something
}
}
All the data for the tests come from factories, and are generated on the fly per test.
Upvotes: 0
Views: 1120
Reputation: 40690
Well the easy but dirty thing to do is to fake a saving failiure through the saving
event:
Here's the note from the event handler:
public function save(array $options = [])
{
$query = $this->newModelQuery();
// If the "saving" event returns false we'll bail out of the save and return
// false, indicating that the save failed. This provides a chance for any
// listeners to cancel save operations if validations fail or whatever.
if ($this->fireModelEvent('saving') === false) {
return false;
}
....
Therefore something like the following should work:
class TestModelSaving {
public function testSaveFailureLogs() {
// Create the fake model here
// If the event handler for saving returns false then `save()` will return false
Customer::saving(function () { return false; });
// Call your unit under test here
// Cleanup: Usually unnecessary, but some test configurations might need it
Customer::flushEventListeners();
}
}
In order to test if things are logged you could mock the logger facade via Log::shouldReceive(....)
(parameters are the same for the mockery function with the same name)
Upvotes: 1