如何使用mockery/mockery为Laravel DB门面的when方法创建测试桩
你需要为when方法创建测试桩,若要同时验证闭包内的逻辑是否正确执行,可参考以下实现方案:
完整测试代码(支持闭包逻辑验证)
public function test_example() { // 创建查询构造器Mock对象 $queryMock = \Mockery::mock(\Illuminate\Database\Query\Builder::class); // 模拟DB::table调用,返回构造器Mock DB::shouldReceive('table') ->once() ->with('users') ->andReturn($queryMock); // 模拟when方法,对齐Laravel原生逻辑,条件成立时执行闭包 $queryMock->shouldReceive('when') ->once() ->with(true, \Mockery::type(\Closure::class)) ->andReturnUsing(function ($condition, $closure) use ($queryMock) { if ($condition) { $closure($queryMock); } return $queryMock; }); // 验证闭包内的where方法是否被正确调用 $queryMock->shouldReceive('where') ->once() ->with('email_verified_at', null) ->andReturnSelf(); // 模拟get方法调用 $queryMock->shouldReceive('get') ->once() ->andReturn(collect([])); // 执行业务代码 (new \App\TestRepo())->testQb(); $this->assertTrue(true); }
简化版测试代码(仅保证不报错,不验证闭包逻辑)
如果不需要校验闭包内的执行逻辑,仅需要测试跑通,可以用更简单的桩实现:
public function test_simple() { DB::shouldReceive('table')->once()->with('users')->andReturnSelf(); DB::shouldReceive('when')->once()->andReturnSelf(); DB::shouldReceive('get')->once()->andReturn(collect([])); (new \App\TestRepo())->testQb(); $this->assertTrue(true); }
核心说明
- 单独创建查询构造器的Mock对象,而非复用DB门面自身作为返回值,更贴合Laravel的实际运行逻辑:
DB::table()本身会返回Illuminate\Database\Query\Builder实例,而非DB门面实例。 - 使用
andReturnUsing处理when的桩逻辑,可以完全复现原生when的行为,确保闭包被正确触发。 - 对
where方法增加调用校验,可以确保闭包逻辑确实被执行,且参数符合预期,测试覆盖度更高。
内容的提问来源于stack exchange,提问作者KevDev
相关产品推荐
相关产品推荐

