0

i am unit testing in laravel with Phpunit. The situation is i have to return a model instance from the controller back to the testing class. There i will use the attributes of that object to test an assertion. How can i achieve that?

Currently i am json encoding that instance into the response. And using it in a way that works but is ugly. Need a clearer way.

This is my test class:

/** @test
*/
function authenticated_user_can_create_thread()
{
    //Given an authenticated user

    $this->actingAs(factory('App\User')->create());

    //and a thread

    $thread = factory('App\Thread')->make();

    //when user submits a form to create a thread

    $created_thread = $this->post(route('thread.create'),$thread->toArray());

    //the thread can be seen

    $this->get(route('threads.show',['channel'=>$created_thread->original->channel->slug,'thread'=>$created_thread->original->id]))
        ->assertSee($thread->body);
}

and this is the controller method:

public function store(Request $request)
{
    $thread = Thread::create([
        'user_id'=>auth()->id(),
        'title'=>$request->title,
        'body'=>$request->body,
        'channel_id'=>$request->channel_id,
    ]);

    if(app()->environment() === 'testing')
    {
       return response()->json($thread);   //if request is coming from phpunit/test environment then send back the creted thread object as part of json response
    }

    else 
        return redirect()->route('threads.show',['channel'=>$thread->channel->slug,'thread'=>$thread->id]);
}

As you can see in the test class, i am receiving the object returned from controller in the $created_thread variable. However, controller is returning an instance of Illuminate\Foundation\Testing\TestResponse, so the THREAD that is embedded in this response is not easy to extract. You can see i am doing --> $created_thread->original->channel->slug,'thread'=>$created_thread->original->id]. But i am sure there is a better way of achieving the same thing.

Can anyone please guide me to the right direction?

Yeasir Arafat Majumder
  • 1,222
  • 2
  • 15
  • 34

1 Answers1

0

PHPUnit is a unit testing suite, hence the name. Unit testing is, by definition, writing tests for each unit -- that is, each class, each method -- as separately as possible from every other part of the system. Each thing users could use, you want to try to test that it -- and only it, apart from everything else -- functions as specified.

Your problem is, there is nothing to test. You haven't created any method with logic which could be tested. Testing controllers action is pointless, as it only proves that controllers are working, which is a Laravel creators thing to check.

lchachurski
  • 1,770
  • 16
  • 21
  • I am testing here the functionality that authenticated user can create a thread. You can see the assertion in the last line of the test method which assets that the created thread is visible when user tries to visit this in the browser. I am not testing controller action here! And infact this is exactly how Jeffery is doing it in latacast!! – Yeasir Arafat Majumder Oct 25 '17 at 21:55
  • Still, authentication and data persisting are laravels core features, right? Anyway, since you want to do it, try to check if your data is saved this way https://laravel.com/docs/5.5/database-testing . Environment condition is a big no-no :) Here is a nice example of a useful unit test https://github.com/laravel/framework/blob/5.5/tests/Config/RepositoryTest.php As you can see this test setups a class and tests its behavior. – lchachurski Oct 31 '17 at 14:59