Ad

PHPUnit Always Takes Me To Login Page,. Regardless Of What I Do

- 1 answer

So I am having a bit of an interesting problem. I am trying to build a forum for my website. I am trying to create a test that ensures registered users can submit new forum threads. Now, regardless of what I do, the test always ends up at the login paghe, even though I am logged in.

Here is something interesting, however, when I attempt to dd() the thread immediately after creation, Laravel seems to "skip over" the dd command and I end up with the "Thread title not found on the login page" error. I can dd() the $request object and that prints out fine, however, it seems after creating a new Thread model does Laravel skip over the dd($thread) command and I end up getting the login page once again.

I am pulling my hair out. Why is this happening?

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;
use App\Thread;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class CreateThreadsTest extends TestCase
{

    use DatabaseMigrations;

    function test_an_authenticated_user_can_create_new_forum_threads() {
            $this->be(factory('App\User')->create());

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

            $this->post('forum/threads', $thread->toArray());

            // you are missing this line
            $this->get($thread->path())->assertSee($thread->title)->assertSee($thread->body);


        }



}
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Thread;
class ThreadsController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $threads = Thread::latest()->get();
        return view('threads.index', compact('threads'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
       $thread = Thread::create([
            'user_id' => auth()->id,
            'title' => $request->title,
            'body' => $request->body
        ]);



       return redirect($thread->path());
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(Thread $thread)
    {
        return view('threads.show', compact('thread'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Thread extends Model
{
    protected $guarded = [];
    public function path() {
        return "/forum/threads/" . $this->id;
    }

    public function replies() {
        return $this->hasMany(Reply::class);
    }

    public function creator()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    public function addReply($reply) {
        $this->replies()->create($reply);
    }
}

Ad

Answer

When you make a new model using the factory helper, it doesn't have an ID

for example

enter image description here

So $thread->path() will return just "/forum/threads/" which is not what you want

You have to make the request to the location from the response or query the newly created Thread record

public function test_users_can_create_statuses()
{
  $this->be(factory('App\User')->create());
  $thread = factory('App\Thread')->make();
  $response = $this->post('/forum/threads', $thread->toArray());
  $this->get($response->headers->get('Location'))
             ->assertSee($thread->title);
             ->assertSee($thread->body);
}
Ad
source: stackoverflow.com
Ad