Laravel 场景下如何 Mock 模型类中已完成单元测试的自定义方法
完全可以对模型的calculateSomething方法进行Mock,根据你提供的两种Service调用场景,有不同的实现方案,这里以PHP生态常用的PHPUnit + Mockery测试框架为例给出实现方式:
场景1:测试myMethodIsolated方法(接收单模型实例参数)
这种场景实现最简单,直接Mock单个MyModel实例的目标方法即可:
public function test_my_method_isolated() { // 创建模型Mock对象,仅mock calculateSomething方法,保留其他原有逻辑 $mockModel = \Mockery::mock(MyModel::class)->makePartial(); // 指定方法返回值为true $mockModel->shouldReceive('calculateSomething')->andReturn(true); // 实例化Service,传入mock的模型实例 $service = new MyService(); $result = $service->myMethodIsolated($mockModel); // 此处添加对应的业务逻辑断言 // ... }
场景2:测试myMethod方法(方法内部调用MyModel::all()获取模型集合)
这种情况需要同时Mock模型的静态查询方法all(),让它返回我们提前构造好的、包含Mock模型实例的集合:
public function test_my_method() { // 构造2个mock的模型实例,分别指定不同的返回值覆盖两个业务分支 $mockModel1 = \Mockery::mock(MyModel::class)->makePartial(); $mockModel1->shouldReceive('calculateSomething')->andReturn(true); $mockModel2 = \Mockery::mock(MyModel::class)->makePartial(); $mockModel2->shouldReceive('calculateSomething')->andReturn(false); // Mock MyModel的静态all方法,返回包含上述mock实例的集合 MyModel::shouldReceive('all')->andReturn(collect([$mockModel1, $mockModel2])); // 调用Service方法 $service = new MyService(); $result = $service->myMethod(1); // 此处添加对应的业务逻辑断言,比如验证true/false分支都被正确执行 // ... }
注意事项
- 如果是基于Laravel框架开发,不需要额外引入Mockery,框架原生自带相关测试工具支持;测试结束后可以通过
Mockery::close()或者使用框架自带的MockeryPHPUnitIntegrationtrait自动清理Mock对象,避免不同测试用例之间互相干扰。 - 这种Mock方式完全符合测试隔离原则,你已经单独验证过
calculateSomething的逻辑正确性,在上层测试中直接Mock返回值是非常合理的实践,可以大幅简化测试用例的编写复杂度。
内容的提问来源于stack exchange,提问作者Mistre83
相关产品推荐
相关产品推荐

