Laravel 5.5中如何测试内部创建对象的方法调用情况?
在Laravel 5.5中测试类内部对象的方法调用
嗨,针对你的需求,要验证调用A::createQuery($variable)时B类的指定方法是否被调用,我们可以借助Laravel默认集成的Mockery工具来实现。核心思路是通过模拟B类的实例,替换掉A类中直接创建的真实B对象,从而跟踪方法的调用情况。下面是具体的实现步骤:
1. 调整A类的结构(提升可测试性)
原代码中A::createQuery直接new B(),导致我们无法替换成模拟对象。我们可以提取一个创建B实例的工厂方法,这样在测试时就能轻松替换它的返回值:
class A { // 新增受保护的工厂方法,用于创建B实例 protected static function createB($variable) { return new B($variable); } public static function createQuery($variable){ $b = static::createB($variable); // 改用工厂方法创建实例 if($variable === 1){ $b->withShoes(); } if($variable === 2){ $b->withSocks(); } if($variable === 1 || $variable === 3){ $b->withFriends(); } return $b->get(); } }
这个改动很小,但能大幅提升代码的可测试性,同时不影响原有功能。
2. 编写测试用例
接下来我们编写测试类,验证不同$variable值下B类方法的调用情况:
use Mockery; use Tests\TestCase; class ATest extends TestCase { /** * 测试当$variable=1时,withShoes和withFriends被调用 */ public function testCreateQueryCallsWithShoesAndFriendsWhenVariableIs1() { // 1. 创建B类的模拟对象 $mockB = Mockery::mock(B::class); // 2. 设置预期:withShoes方法被调用1次,链式调用需返回自身 $mockB->shouldReceive('withShoes') ->once() ->andReturnSelf(); // 3. 设置预期:withFriends方法被调用1次 $mockB->shouldReceive('withFriends') ->once() ->andReturnSelf(); // 4. 设置预期:get方法被调用1次,并返回测试用结果 $mockB->shouldReceive('get') ->once() ->andReturn('test-result'); // 5. 替换A类的createB方法,返回我们的模拟对象 $this->mock(A::class, function ($mock) use ($mockB) { $mock->shouldReceive('createB') ->with(1) ->andReturn($mockB); }); // 6. 调用待测试的方法 $result = A::createQuery(1); // 7. 验证返回结果(可选,根据需求添加) $this->assertEquals('test-result', $result); } /** * 测试当$variable=2时,withShoes不会被调用 */ public function testCreateQueryDoesNotCallWithShoesWhenVariableIs2() { $mockB = Mockery::mock(B::class); // 设置预期:withShoes永远不会被调用 $mockB->shouldReceive('withShoes') ->never(); // 设置预期:withSocks被调用1次 $mockB->shouldReceive('withSocks') ->once() ->andReturnSelf(); $mockB->shouldReceive('get') ->once() ->andReturn('test-result'); $this->mock(A::class, function ($mock) use ($mockB) { $mock->shouldReceive('createB') ->with(2) ->andReturn($mockB); }); A::createQuery(2); } // 测试结束后清理Mockery资源 protected function tearDown(): void { parent::tearDown(); Mockery::close(); } }
关键说明
- Mockery核心作用:模拟
B类的实例,我们可以精确指定某个方法是否被调用、调用次数、传入参数等。如果实际调用不符合预期,测试会直接失败。 - 工厂方法的意义:通过提取
createB方法,我们避免了在测试中修改A类的核心逻辑,同时实现了对B实例的替换。 - 链式调用处理:因为
B类的方法是链式调用(比如$b->withShoes()->get()),所以我们需要在模拟时用andReturnSelf()来维持链式结构。
运行测试后,如果方法调用不符合预期,Mockery会抛出明确的错误提示,帮助你快速定位问题。
内容的提问来源于stack exchange,提问作者Z.S
相关产品推荐
相关产品推荐

