laracoft's avatar

Model does not seem to refresh/fresh in test

I have the following test that intermittently fails. It always passes if I put a breakpoint before asserting, seems to be a race condition, but I can't pinpoint where. Tests are being done on a real MySql database.

I also tried both $updated = $d->fresh(); and $d->refresh(); and they always fail (not intermittently).

How do I make sure $updated indeed gets reloaded?

public function test_Can_activate_device()
{
    $hardware_id = "1234-5678-90ab-cdef-1234";
    $d = Device::make();
    $d->hardware_id = $hardware_id;
    $d->is_active = 0;
    $d->save();

    $da = Device_activation::make();
    $da->hash = bcrypt($hardware_id);
    $da->device()->associate($d);
    $da->expired_at = Carbon::now()->addDay(3);
    $da->save();

    $response = $this->call('GET', "/activate/{$da->hash}"); // this causes $d->is_active to become 1

    $updated = Device::where('id', $d->id)->first()->fresh(); // test passes if I put a breakpoint here

    $this->assertEquals(1, $updated->is_active);
}
0 likes
9 replies
neilstee's avatar

@laracoft you sure deactivating really works? Meaning you can see on your database that is_active becomes 1?

Also, I don't see any point in doing ->fresh().

$updated = Device::where('id', $d->id)->first(); // this should be fine

I think the issue is here:

$response = $this->call('GET', "/activate/{$da->hash}");

Your code below is running while in fact the device is not yet activated. You can confirm it by:

$response = $this->call('GET', "/activate/{$da->hash}");

$updated = Device::where('id', $d->id)->first();

dd($updated->is_active);

if it shows 0 then that's really the issue.

neilstee's avatar

@laracoft

Also since you are testing the endpoint, it might be a good idea to test the response of it as well instead of just testing the Device:

$response = $this->get("/activate/{$da->hash}");
$response->assertStatus(200);
$response->assertJson($yourExpectedJsonArray);
laracoft's avatar

Thanks, yes, I'm aware of testing the response, but shortened my code to demonstrate where the problem is.

After a few runs, $updated = Device::where('id', $d->id)->first()->fresh(); seems ok now.

Do you know why $updated = $d->fresh(); and $d->refresh(); does not work? I'm trying to keep my code short and easy to read.

neilstee's avatar
neilstee
Best Answer
Level 34

@laracoft so what fixes your issue then? As I've said, you don't need ->fresh() on the $updated variable because it's a new selected data.

To shorten your testing, I would do something like this:

public function test_Can_activate_device()
{
    $hardware_id = "1234-5678-90ab-cdef-1234";
    $device = Device::make();
    $device->hardware_id = $hardware_id;
    $device->is_active = 0;
    $device->save();

    $deviceActivation = Device_activation::make();
    $deviceActivation->hash = bcrypt($hardware_id);
    $deviceActivation->device()->associate($device);
    $deviceActivation->expired_at = Carbon::now()->addDay(3);
    $deviceActivation->save();

    $response = $this->get("/activate/{$deviceActivation->hash}"); 

	$device = $device->fresh();

    $this->assertEquals(1, $device->is_active);
}

You need to re-assigned $device on $device = $device->fresh() to make it work.

I also replaced your $d and $da to $device and $deviceActivation. A unit test should be as readable as possible IMO because developers consider it documentation of their code.

laracoft's avatar

@neilstee to be honest, I'm not exactly sure what has changed, I'm on dev and much of the changes are not tracked by git. But I was sure that when I did a breakpoint with xdebug, the test passed and it failed when I did not have a breakpoint enabled.

Anyway, thanks for your help and suggestions!

1 like
laracoft's avatar

I'm not sure what happened earlier, but $d->fresh() works now and I was sure $d->is_active was updated after the HTTP call.

neilstee's avatar

@laracoft check my recent reply, $d->fresh() alone won't work. You need to put it again on $d or to another variable.

laracoft's avatar

Yes, I'm aware of the difference and typed wrongly earlier, it was $d->refresh() (not $d->fresh())

neilstee's avatar

@laracoft well glad it works now, I think you can close now this thread by marking one of the replies (even yours) as "Best Answer" so others can find it useful as well 😉

Please or to participate in this conversation.