Laravel中Mockery模拟Eloquent链式查询的参数验证问题
解决Laravel中Mockery模拟链式查询并验证参数的问题
要正确测试User::where("name", "test")->first()这类链式调用,核心是要模拟Eloquent Builder实例——因为where方法返回的是Builder而非User模型本身。具体实现步骤如下:
创建User模型的静态Mock
继续使用你已有的别名Mock拦截User的静态方法调用:$userMock = \Mockery::mock('alias:App\Models\User');创建Eloquent Builder的Mock实例
由于where方法需要返回Builder对象,单独模拟这个实例:$builderMock = \Mockery::mock(\Illuminate\Database\Eloquent\Builder::class);模拟User的静态where方法,验证参数并返回Builder Mock
指定where的传入参数,同时让它返回刚才创建的Builder Mock:$userMock->shouldReceive('where') ->withArgs(['name', 'test']) // 验证where的参数是否符合预期 ->andReturn($builderMock);模拟Builder的first方法,返回预期的User实例
让Builder的first方法返回你需要的User对象(可以是真实实例或另一个Mock):// 示例:创建预期的User实例 $expectedUser = new \App\Models\User(['name' => 'test']); // 也可以用Mock:$expectedUser = \Mockery::mock(\App\Models\User::class); $builderMock->shouldReceive('first') ->andReturn($expectedUser);
这样设置后,代码执行User::where("name", "test")->first()时,既会验证where方法的参数是否正确,又能让链式调用正常返回预期的User实例。
为何之前的写法失效?
你之前直接让where返回User实例,但链式调用的first是Eloquent Builder的方法,User模型本身并没有这个方法,因此调用会失败。必须通过模拟Builder实例来衔接链式调用的每一步。
内容的提问来源于stack exchange,提问作者vonBerg
相关产品推荐
相关产品推荐

