Laravel升级后PHPUnit测试未检测控制器不存在问题求助
解决Laravel测试中“Failed asserting that null matches expected 1”的问题
咱们一步一步拆解你的问题,先搞清楚为什么没出现控制器不存在的错误,再解决断言失败的问题:
为什么没收到“控制器不存在”的错误?
Laravel在测试环境中,默认的异常处理会把控制器/方法不存在这类错误转换成404响应,但你的测试没有断言响应的状态码,所以测试会继续执行后面的代码。而此时因为控制器逻辑压根没跑,员工和群组的关联关系根本没建立,$employee->groups(这是个关联集合)因为没加载且没有数据,就返回了null,才导致断言失败。
解决步骤
1. 先完成控制器的逻辑
你得先创建ManageEmployeeController并实现group方法,不然请求根本不会处理关联关系的存储:
namespace App\Http\Controllers; use App\Employee; use Illuminate\Http\Request; class ManageEmployeeController extends Controller { public function group(Request $request, Employee $employee) { // 先验证请求的群组ID是否合法 $request->validate([ 'groups' => 'array|exists:groups,id' ]); // 使用sync方法同步员工的群组(适合多对多关联) $employee->groups()->sync($request->input('groups')); // 返回响应,这里用重定向示例,你可以根据需求调整 return redirect()->back(); } }
注:这里假设你的Employee模型和Group模型已经定义了多对多的关联关系(比如Employee里有groups()方法返回$this->belongsToMany(Group::class))。
2. 修正测试中的断言逻辑
你的测试有两个问题:
- 直接用
$employee->groups是关联集合对象,不是数量,而且内存中的$employee对象不会自动同步数据库的更新; - 没有重新从数据库加载员工,导致拿不到最新的关联数据。
修改后的测试代码:
/** @test */ public function it_assigns_an_employee_to_a_group() { $group = factory(Group::class)->create(); $employee = factory(Employee::class)->create(); $this->post(route('employee.manage.group', $employee), [ 'groups' => [$group->id] ]); // 刷新员工对象,从数据库获取最新数据 $employee->refresh(); // 方法一:断言员工的群组数量为1 $this->assertEquals(1, $employee->groups()->count()); // 方法二:更严谨的断言,确认该员工确实关联了指定的群组 $this->assertTrue($employee->groups->contains($group)); }
3. 可选:添加响应状态码断言,提前发现问题
为了避免以后再出现这类“控制器没写但测试没提示”的情况,可以在请求后加上响应断言,比如:
$this->assertRedirect(); // 对应控制器里的重定向响应 // 或者如果是API接口,可以用$this->assertStatus(200);
这样如果控制器不存在或者逻辑报错,测试会直接在响应断言这里失败,更便于排查问题。
内容的提问来源于stack exchange,提问作者Prince Lionel N'zi
相关产品推荐
相关产品推荐

