【问题标题】:Laravel: Feature Test fails because of added middlewareLaravel:由于添加了中间件,功能测试失败
【发布时间】:2020-04-06 23:59:53
【问题描述】:

用户注册并验证其电子邮件后,他们必须使用其他信息完成注册。这发生在/register/complete-signup

这个问题对我来说完全没有意义。

无论出于何种原因,当我添加中间件 has-not-completed-signup 时,测试开始失败,因为 App\User 不再具有通过 attach() 在控制器中发生的关联 App\Account

只要我从路由中删除我的中间件,它就可以正常工作。

我的中间件可以防止已经完成注册的用户访问或发布到这些路由。我在浏览器中测试并且重定向有效。控制器方法正在测试中使用,我可以dd($account->users) 并得到正确的响应。但是如果我做$user->accounts,集合是空的。

删除中间件后,$user->accounts 不再为空。但是我在中间件中做了一个dd(),它甚至没有运行(这是正确的,因为用户没有帐户)。

那么为什么这会让它失败呢?我完全迷路了。

我试图在下面包含所有相关信息。如果您还有其他需要,请告诉我。

编辑:

在我的中间件中,我已经注释掉了功能。关于检查雄辩关系的某些事情使我测试失败。我不知道为什么。

这会使测试失败:

if (!auth()->user()->accounts->isEmpty()) {      
  //return redirect(RouteServiceProvider::HOME);
}

例如,如果我将其更改为像这样无用的东西,它会起作用:

if (auth()->user()) {
//return redirect(RouteServiceProvider::HOME);
}

我可以做到 $account->users ,但是当我使用中间件时 $user->accounts 在控制器上返回空集合


原文:

这是我的路线:

// auth scaffolding
Auth::routes(['verify' => true]);

// main app routes
Route::middleware('verified', 'auth')->group(function() {

    // User verified and has an App\Account
    Route::middleware('completed-signup')->group(function() {
        Route::get("/", 'HomeController@index' )->name('home');
        Route::get('/paywall', 'BillingController@paywall')->name('paywall');

    });

    // The user hasn't attached an App\Account to their User
    Route::middleware('has-not-completed-signup')->group(function() {
        Route::get("/register/complete-signup", 'AccountController@showCompleteSignup' )->name('complete-signup');
        Route::post('/register/complete-signup', 'AccountController@storeCompleteSignup')->name('complete-signup.store');
    });

});

has-not-completed-signup中间件:

    public function handle($request, Closure $next)
    {
        if (auth()->user()->hasCompletedAccountSetup()) {

            return redirect(RouteServiceProvider::HOME);
        }

        return $next($request);
    }

应用/用户方法:

Class User extends Authenticatable implements MustVerifyEmail { 
...

    public function accounts() {
        return $this->belongsToMany('App\Account', 'account_role_user')->withPivot('role_id');
    }
    public function hasCompletedAccountSetup() {
        return !$this->accounts->isEmpty();
    }
    ...

AccountController@storeCompletedSignup:

    public function storeCompleteSignup(Request $request) {

        $validatedData = $request->validate([
            'company' => 'required|max:255',
            'contact_state' => 'required|max:255',
            'contact_country' => 'required|max:255',
            'contact_zip' => 'required|max:255',
            'contact_city' => 'required|max:255',
            'contact_phone' => 'nullable|max:255',
            'contact_address_1' => 'required|max:255',
            'contact_address_2' => 'nullable|max:255',
            'contact_first_name' => 'required',
            'contact_last_name' => 'required',
            'contact_email' => 'required'
        ]);

        $user = auth()->user();

        $account = new Account($validatedData);

        $account->contact_first_name = $user->first_name;
        $account->contact_last_name = $user->last_name;
        $account->contact_email = $user->email;

        $account->save();



        $account->users()->attach(
            $user->id, 
            ['role_id' => Role::where('name', 'owner')->first()->id ]
        );

        return $request->wantsJson()
                    ? new Response('Signup Completed Successfully', 201)
                    : redirect()->route('/');

    }

我的测试:


    /**
     * @test
     */
    public function a_user_can_complete_signup()
    {


        $user = Factory('App\User')->create();
        $this->actingAs($user);

        $accountAttributes = factory('App\Account')->raw([
            'contact_first_name' => "TEST",
            'contact_last_name' => $user->last_name,
            'contact_email' => $user->email,
            'contact_country' => "USA"
        ]);

        $res = $this->post('/register/complete-signup', $accountAttributes);

        $res->assertSessionDoesntHaveErrors();

        $this->assertTrue( !$user->accounts->isEmpty() ); // THIS FAILS
        $this->assertTrue( $user->accounts->first()->company == $accountAttributes['company']);
        $this->assertTrue( $user->accounts->first()->contact_first_name == $user->first_name );


    }

【问题讨论】:

    标签: laravel phpunit


    【解决方案1】:

    问题实际上不在于中间件,而是因为我必须在测试 POST 后刷新模型。

    $this->assertTrue( !$user->accounts->isEmpty() );

    需要成为

    $this->assertTrue( !$user->fresh()->accounts->isEmpty() );

    通过了测试。

    我知道 fresh 和 refresh() 方法,但导致问题的中间件对我来说没有意义。

    【讨论】:

      猜你喜欢
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2016-03-05
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多