Home > Back-end >  Laravel best approach for Testing if a value will change
Laravel best approach for Testing if a value will change

Time:04-12

The code

I have a database, which has a table for Teams and Instructors along the lines of:

| id | team_id | instructor_id | ... |

Every 24 hours a batch runs that updates the instructor for that team.
What I need to create is a simple Test to check if the batch is running properly, and the instructor is changed.

The Issue

The batch updates the instructor randomly, meaning that the same instructor might get chosen twice, throwing an error when running the test. I tried checking if the updated_at column changes, but it seems like when the same values are passed to update() Laravel does not change said column.

The question

How am I supposed to check if the instructor changes?
I am only assigned to making the test, so I should not change the way the batch operates (like forcing it so that updated_at changes)
However making a for loop until the instructor is changed looks very ugly.
And since there are only between 3 to 5 instructors, the chances of the same instructor being picked a few times in a row is not that low.

Update

Here is the code as requested.
The test file:

class InstructorSelectionOrderTest extends TestCase
{
    use RefreshDatabase;

    ...

    /**
     * @test
     * @group instructorSelection
     *
     * @return void
     */
    public function test_old_team_instructor_random()
    {
        $team = factory(RoutineTeam::class)->create(['instructor_id' => 4, 'updated_at' => Carbon::now()->subDays(1)]);
        $room = factory(Room::class)->create(['team_id' => $team->id]);

        $this->createNewUser($team->id, $room->id);

        $this->artisan('project:reassign_instructors')->assertExitCode(0);

        $result = RoutineTeam::where('id', $team->id)->get();

        $this->assertFalse($result[0]->updated_at == $team->updated_at);
    }

The batch:

class ReassignInstructors extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'project:reassign_instructors';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //list of rooms that needs to be updated
        $routineTeams = RoutineTeam::openedRoomTeams();

        ...

        foreach ($routineTeams as $routineTeam) {
            //Instructor::getRandomInstructor()->id = random number from 1 to 4
            $routineTeam->instructor_id = Instructor::getRandomInstructor()->id;
            $routineTeam->save();
        }

        return 0;
    }
}

The RoutineTeam table:

| id | team_id | instructor_id | ... | updated_at

The test currently has a 25% chance of failing. I can only edit the test file. Is there a way to make it a 0% chance of failing only by changing the test file?

CodePudding user response:

Since the instructor id is static in your text, I'm guessing there is no foreign key constraint on it.

So, why not set the instructor_id to 0 and then run the job (or any non existing id).

 /**
     * @test
     * @group instructorSelection
     *
     * @return void
     */
    public function test_old_team_instructor_random()
    {
        //setting the id to 0 so it is forced to change on 'project:reassign_instructors' command
        $team = factory(RoutineTeam::class)->create(['instructor_id' => 0, 'updated_at' => Carbon::now()->subDays(1)]);
        $room = factory(Room::class)->create(['team_id' => $team->id]);

        $this->createNewUser($team->id, $room->id);

        $this->artisan('project:reassign_instructors')->assertExitCode(0);

        $result = RoutineTeam::where('id', $team->id)->get();

        $this->assertFalse($result[0]->updated_at == $team->updated_at);
    }
  • Related