The following test fails :
/** @test */
public function set_shift_on_given_availability_to_a_candidate()
{
$candidate = $this->createCandidateWithFixedAvailability(pow(2, 3) - 1);
$candidate->availabilities[0]->setShift(App\Availability::SHIFT_TYPES['AM']);
$candidateShifts = $candidate->availabilities[0]->shifts;
$this->assertEquals(count($candidateShifts), 1);
$this->assertTrue(in_array('AM', $candidateShifts));
}
When I try using the methods with artisan tinker I get the expected results:
>>> $candidate->availabilities()->first()->shifts();
=> [
"AM",
]
>>> $candidate->availabilities()->first()->setShift(App\Availability::SHIFT_TYPES['PM']);
=> null
>>> $candidate->availabilities()->first()->shifts();
=> [
"PM",
]
Implementation details of methods used :
public function setShift(...$shiftTypes)
{
\DB::table($this->table)
->where([
['candidate_id', '=', $this->candidate_id],
['day_of_week_id', '=', $this->day_of_week_id]
])
->update(['shifts' => array_sum ($shiftTypes)]);
}
public function shifts()
{
$namedShifts = [];
foreach (Availability::SHIFT_TYPES as $key => $val) {
if($this->shifts & $val) {
array_push($namedShifts, $key);
}
}
return $namedShifts;
}
I am using a separate test database with the DatabaseTransactions trait. I don't understand why the update is not changing the column values when I attempt to get the columns value with shifts() in my unit test while it works with tinker.
From what I can see, using the DB query builder to update the column then fetching the dynamic property of that column does not reflect the update change, so either I fetch it using the query builder or I assign the shift value to the dynamic property in the setShift function when an update runs successfully. It's just odd that the dynamic property is correctly updated in tinker, but not in phpunit.
The main difference between your testing setup and the Tinker example is the usage of $candidate->availabilities()->first()
vs $candidate->availabilities[0]
.
$candidate->availabilities()
is probably set up to return a HasMany
relation. Calling $candidate->availabilities()->first()
will thus execute an SQL statement directly on the database.
$candidate->availabilities[0]
resolves the availabilities
relation. This can have "side effects" e.g. because the relation is already set up so that no "fresh" call to the DB is triggered. I guess that $this->createCandidateWithFixedAvailability(pow(2, 3) - 1);
does not work as intended. Maybe you are creating the availabilities
without actually saving them correctly so that certain properties are not set. A common error in this scenario is missing relation values (e.g. the candidate_id
property in the availability
entity isn't set).
Now, this is all pretty speculative and purely based on the errors I found myself running into in the past ;)