Laravel中如何用PHPUnit和Mockery断言服务构造函数参数
解决方案
要验证ServiceOne调用testOne时是否向ServiceTwo的构造函数传入了正确参数,你可以采用以下两种可靠方案:
方案1:通过容器绑定回调捕获并验证参数
直接借助Laravel容器的绑定回调机制,在解析ServiceTwo时捕获传入的参数并执行断言:
public function testServiceOnePassesCorrectNameToServiceTwo() { $expectedName = 'testing'; // 构建ServiceTwo的Mock,仅验证testTwo方法被调用一次 $serviceTwoMock = \Mockery::mock(ServiceTwo::class) ->shouldReceive('testTwo') ->once() ->getMock(); // 绑定ServiceTwo到容器,回调中捕获参数并断言 $this->app->bind(ServiceTwo::class, function ($app, $parameters) use ($serviceTwoMock, $expectedName) { $this->assertEquals($expectedName, $parameters['name'], 'ServiceTwo构造函数的name参数不符'); return $serviceTwoMock; }); // 执行测试方法 app(ServiceOne::class)->testOne($expectedName); }
当ServiceOne调用app(ServiceTwo::class, ['name' => $name])时,容器会将传入的参数数组传递给绑定回调的$parameters变量,此时即可直接验证参数的准确性。若参数不符合预期,断言会立即失败并给出明确提示。
方案2:使用Mockery构造函数参数验证
利用Mockery的shouldBeConstructedWith方法,直接指定ServiceTwo实例化时必须接收的参数:
public function testServiceOnePassesCorrectNameToServiceTwo() { $expectedName = 'testing'; // 创建Mock时,同时验证构造函数参数和testTwo方法调用 $serviceTwoMock = \Mockery::mock(ServiceTwo::class) ->shouldBeConstructedWith([$expectedName]) ->shouldReceive('testTwo') ->once() ->getMock(); // 将Mock实例绑定到容器 $this->app->instance(ServiceTwo::class, $serviceTwoMock); // 执行测试方法 app(ServiceOne::class)->testOne($expectedName); }
该方案会直接验证Mock被构造时是否传入了预期参数。如果ServiceOne传入的参数错误,Mockery会抛出断言失败异常,终止测试。
关键说明
- 方案1更灵活,支持对参数进行复杂验证(比如正则匹配、类型检查等);方案2更简洁,直接利用Mockery的内置断言能力。
- 确保测试类中已正确引入Mockery,且在测试完成后清理Mock(Laravel项目的测试基类通常会在
tearDown方法中自动执行Mockery::close())。
内容的提问来源于stack exchange,提问作者fico7489
相关产品推荐
相关产品推荐

