Menu

6.用户能够发布话题

本节说明

  • 对应视频第 6 小节:A User Can Publish Threads

本节内容

首先新建测试文件:

$ php artisan make:test CreateThreadsTest

编写测试逻辑:
\tests\Feature\CreateThreadsTest.php

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class CreateThreadsTest extends TestCase
{
    /** @test */
    public function an_authenticated_user_can_create_new_forum_threads()
    {
        // Given we have a signed in user
        // When we hit the endpoint to cteate a new thread 
        // Then,when we visit the thread
        // We should see the new thread
    }
}

接着填充具体代码:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class CreateThreadsTest extends TestCase
{
    use DatabaseMigrations;

    /** @test */
    public function an_authenticated_user_can_create_new_forum_threads()
    {
        // Given we have a signed in user
        $this->actingAs(factory('App\User')->create());  // 已登录用户

        // When we hit the endpoint to cteate a new thread
        $thread = factory('App\Thread')->make();
        $this->post('/threads',$thread->toArray());

        // Then,when we visit the thread
        // We should see the new thread
        $this->get($thread->path())
            ->assertSee($thread->title)
            ->assertSee($thread->body);
    }
}

注1:关于create()make()rw()三种方法的比较,详见课后附注处。

运行测试:

$ APP_ENV=testing phpunit --filter an_authenticate

测试未通过:
file
因为还未添加路由,前往添加:
web.php

.
.
Route::get('/home', 'HomeController@index')->name('home');
Route::get('/threads','ThreadsController@index');
Route::post('/threads','ThreadsController@store');  -->此处添加路由
Route::get('/threads/{thread}','ThreadsController@show');
Route::post('/threads/{thread}/replies','RepliesController@store');

修改store()方法:
\app\Http\Controllers\ThreadsController.php

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

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

再次测试,测试通过:
file
接下来我们可以编写测试,未登录用户不能添加thread
\tests\Feature\CreateThreadsTest.php

class CreateThreadsTest extends TestCase
{
    use DatabaseMigrations;

    /** @test */
    public function guests_may_not_create_threads()
    {
        $thread = factory('App\Thread')->make();
        $this->post('/threads',$thread->toArray());
    }
    .
    .

此时如果我们运行测试的话:
file
仍然新建了thread,只是因为此时auth()->id()null导致user_id的值为null,从而出现了数据库异常,这说明测试未通过。接下来修复此漏洞:
\app\Http\Controllers\ThreadsController.php

class ThreadsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->only('store'); // 白名单,意味着仅 store 方法需要登录
    }

再次测试:
file
正是我们希望看到的。补充完测试代码:
\tests\Feature\CreateThreadsTest.php

/** @test */
public function guests_may_not_create_threads()
{
    $this->expectException('Illuminate\Auth\AuthenticationException'); // 在此处抛出异常即代表测试通过

    $thread = factory('App\Thread')->make();
    $this->post('/threads',$thread->toArray());
}

再次运行测试,测试通过:

file

课后附注

关于create()make()raw()三种方法的比较:

  • create()方法得到一个模型实例,并保存到数据库中;
  • make()方法得到一个模型实例(不保存);
  • raw()方法是得到一个模型实例转化后的数组。

本文章首发在 Laravel China 社区
上一篇 下一篇
讨论数量: 0
发起讨论


暂无话题~
刻意练习,每日精进。
3
点赞
385
浏览
0
讨论

维护者
14
14