Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

webRookie's avatar

is this a good way to test if the controller sends the desired collection to the view?

here is my code

is this a good way to test if the controller sends the desired collection to the view? this is correct? It passes but I don't know ->assertSee($quiz->first()->description) ->assertSee($quiz->first()->questions->first()->body);

/*
given there is a quiz that has many questions
when user visit quiz page
see  quiz questions and possible answers
*/


public function test_quiz_id_exist()
{

    $quiz = factory(Quiz::class, 1)
        ->create()
        ->each(function(Quiz $quiz){
            factory(\App\Question::class, 3)
                ->create(['quiz_id'=> $quiz->id]);
        });

    $this->assertInstanceOf(Collection::class, $quiz);

   $request = $this->call('GET','/{id}/quiz', ['id' => 1])
       ->assertViewIs('pages.quizDetails')
       ->assertStatus(200)
       ->assertSee($quiz->first()->description)
       ->assertSee($quiz->first()->questions->first()->body);

}
0 likes
3 replies
JarekTkaczyk's avatar
Level 53

first off, if it works and does what you want it to do, then it's good!

then, I'd suggest something like this:

/** @test */
public function quiz_and_question_are_shown()
{
    $quiz = factory(Quiz::class)->create(['description' => 'Awesome Quiz']);
    $quiz->questions()->save(factory(Question::class)->make(['body' => 'who\'s there?']));
    $quiz->questions()->save(factory(Question::class)->make(['body' => 'how much?']));

    // no need for this - it tests laravel itself:
    // $this->assertInstanceOf(Collection::class, $quiz);

    $this->get($quiz->id.'/quiz')
        // no need - you care here about the end result not view filename
        // ->assertViewIs('pages.quizDetails')
        ->assertStatus(200)
        ->assertSee('Awesome Quiz')
        ->assertSee('who\'s there?');
        ->assertSee('how much?');
}

This requires a bit more typing, yes. But it makes tests a bit easier to understand in a long run. Limiting indirection is a good thing, that future you will thank you for.

alanholmes's avatar

Another option, if you don't want to lock your tests down to what is being displayed in the view, and just that the view gets the correct collection, you can do this.


public function test_quiz_id_exist()
{

    $quiz = factory(Quiz::class)->create(['description' => 'Awesome Quiz']);
    $quiz->questions()->save(factory(Question::class)->make(['body' => 'who\'s there?']));
    $quiz->questions()->save(factory(Question::class)->make(['body' => 'how much?']));

   $request = $this->call('GET','/{id}/quiz', ['id' => 1])
       ->assertViewIs('pages.quizDetails')
       ->assertStatus(200);

  $this->assertTrue($request->original->getData()['quiz']->is($quiz));
}

That way you know that the quiz passed through to the view is the same quiz as you have created.

From there you could expand it to also check that you have the right questions passed through as well.

Both options are fine, its more of a case of if you want your tests to check that you have the correct data for the view, or that the correct output is displayed.

However, if you do test on what is displayed, if you change how something is displayed (not applicable here, but say you change the format of a date output), then it might break your tests.

1 like

Please or to participate in this conversation.