You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何测试路由中间件?Laravel路由示例及测试类型确认

嘿,这个问题问得很实在!我来给你捋清楚这两个关键点:

如何测试这些路由确实受verified中间件保护?

核心思路是模拟两种用户场景:未验证邮箱的用户访问路由时应该被重定向到验证页面,而已验证的用户则能正常访问。用Laravel自带的测试框架(PHPUnit)可以这样写:

首先,测试未验证用户的访问行为(这是重点,因为我们要验证中间件的拦截逻辑):

<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class VerifiedMiddlewareTest extends TestCase
{
    use RefreshDatabase;

    /**
     * 测试未验证用户无法访问受保护的路由
     * @dataProvider protectedRoutesProvider
     */
    public function test_unverified_users_cannot_access_protected_routes(string $routeName)
    {
        // 创建一个未验证邮箱的用户(email_verified_at 字段为 null)
        $unverifiedUser = User::factory()->unverified()->create();

        // 以该用户身份发起请求
        $response = $this->actingAs($unverifiedUser)->get(route($routeName));

        // 断言被重定向到邮箱验证提示页面
        $response->assertRedirect(route('verification.notice'));
    }

    /**
     * 测试已验证用户可以正常访问受保护的路由
     */
    public function test_verified_users_can_access_protected_routes()
    {
        // 创建一个已验证邮箱的用户(默认工厂生成的用户是已验证状态)
        $verifiedUser = User::factory()->create();

        // 测试 profile 路由
        $profileResponse = $this->actingAs($verifiedUser)->get(route('profile.show'));
        $profileResponse->assertOk(); // 断言返回200状态码

        // 测试 settings 路由
        $settingsResponse = $this->actingAs($verifiedUser)->get(route('settings.show'));
        $settingsResponse->assertOk();
    }

    // 数据提供者,避免重复编写测试代码
    public function protectedRoutesProvider()
    {
        return [
            ['profile.show'],
            ['settings.show'],
        ];
    }
}

几点补充说明:

  • 使用RefreshDatabase trait可以保证每次测试都是干净的数据库环境
  • User::factory()->unverified()->create()需要你的User工厂支持unverified状态,比如在工厂里定义一个状态方法:
    public function unverified(): static
    {
        return $this->state(fn (array $attributes) => [
            'email_verified_at' => null,
        ]);
    }
    
  • 如果你的验证提示路由不是默认的verification.notice,记得改成你项目里对应的路由名称
这种测试属于功能测试还是单元测试?

毫无疑问,这属于功能测试。

原因很简单:我们不是在孤立地测试verified中间件这个类的单个方法(那是单元测试的范畴),而是在测试整个请求流程的行为:用户发起请求,中间件拦截/放行,路由最终返回正确的响应。功能测试关注的是系统的整体行为是否符合业务预期,模拟的是真实用户的操作场景。

如果是单元测试,你可能会直接实例化VerifiedMiddleware类,传入模拟的请求和闭包,测试它的handle方法是否正确触发重定向或放行——但那只是测试中间件本身的逻辑,而我们这里的测试是验证路由和中间件的组合是否能正确保护资源,属于功能层面的验证。

内容的提问来源于stack exchange,提问作者rook

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:37:45