Hi,
I've got a problem that had me grinding my gears for several days.
I wrote feature tests for a class, testing each routes with different cases, but here's the thing: every test works fine, except one case for one test.
Here are (some of) my tests:
public function test_get(): void
{
$group = Group::factory()->create();
// Succès
$response = $this->getJson("/api/groups/$group->id");
$response->assertStatus(200)
->assertJsonStructure(self::RESOURCE_STRUCTURE)
->assertJson(["id" => $group->id]);
// Id du groupe invalide
$response = $this->getJson("/api/groups/9999");
$response->assertStatus(422);
}
public function test_update(): void
{
$group = Group::factory()->create();
// Succès
$response = $this->putJson("/api/groups/$group->id", ["label" => "Test2"]);
$response->assertStatus(200)
->assertJsonStructure(self::RESOURCE_STRUCTURE)
->assertJson(["label" => "Test2"]);
// Id du groupe invalide
$response = $this->putJson("/api/groups/9999", ["label" => "Test2"]);
$response->assertStatus(422);
// Corps invalide
$response = $this->putJson("/api/groups/$group->id", ["labl" => "Test2"]);
$response->assertStatus(422);
}
public function test_delete(): void
{
$group = Group::factory()->create();
$groupWithChildren = Group::factory()
->hasAttached(Group::factory(), ["order_number" => 1], "children")
->create();
$test = Test::factory()->create();
$groupWithResults = Group::factory()
->hasAttached($test, ["order_number" => 1])
->has(ResultGroup::factory()
->has(Result::factory()
->for($test)))
->create();
// Test simple
$response = $this->deleteJson("/api/groups/$group->id");
$response->assertStatus(204);
$this->assertModelMissing($group);
// Test groupe avec un parent
$response = $this->deleteJson("/api/groups/{$groupWithChildren->children[0]->id}");
$response->assertStatus(409);
$this->assertModelExists($groupWithChildren->children[0]);
// Test groupe avec des enfants
$response = $this->deleteJson("/api/groups/$groupWithChildren->id");
$response->assertStatus(204);
$this->assertSoftDeleted($groupWithChildren);
// Test groupe avec des résultats
$response = $this->deleteJson("/api/groups/$groupWithResults->id");
$response->assertStatus(204);
$this->assertSoftDeleted($groupWithResults);
}
Everything works, except the case "Test simple" ("Simple test" in french, which should be the most basic test case) for the test_delete() function. The thing is, I don't even get an error message! When I run the test suite with this case commented, it works, when I uncomment it, the terminal freeze for a very long time, then ends without any output (does not end at all).
I run the tests in a docker container by mounting the laravel application in the container. I think it's memory related because one time I managed to have an error saying "Allowed memory size of x bytes exceeded" by checking docker logs on the container. I can't even find that error again because now the command seem to run forever without crashing.
I made all kind of commenting to find the source of the problem, and this particular case is really what make everything goes wrong.
Here is the code that is called by the route if it can help:
GroupController
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(int $id): Response
{
if (($group = Group::find($id)) === null) {
return response("Le groupe n°$id n'existe pas", 422);
} else {
if ($group->delete()) {
return response(null, 204);
} else {
return response("Le groupe est utilisé dans un ou plusieurs groupes", 409);
}
}
}
Group
public function delete(): bool
{
if ($this->parents()->exists()) {
return false;
} else {
parent::delete();
if (!$this->resultGroups()->withTrashed()->exists() && !$this->children()->withTrashed()->exists()) {
$this->tests()->detach();
$this->forceDelete();
}
return true;
}
}
Can anyone tell me what is going wrong with this specific test case?
Is it a docker issue? If that's the case, why everything else works?
Is there some kind of mumbo jumbo laravel does when deleting that cause a loop or massive memory leak?