如何在PHP测试中模拟实现指定接口的ApiAuthRequest类?
问题解答
你在测试类里临时定义实现特定接口的ApiAuthRequest类来通过测试的方式是可行的,但具体是否合适要看你的实际场景,下面详细分析:
为什么这个方法能生效?
PHP允许在测试类内部定义临时类,只要命名空间不冲突就行。你定义的这个临时类满足了ModelRestrictionFactory对HasModelSystemRestriction接口的依赖要求,加上你用partialMock只Mock了必要的getModel方法,自然能通过测试里的类型校验。
这种方式的优缺点
优点
- 不用改生产代码,快速搞定测试依赖问题
- 测试代码独立,不会影响线上的类定义
缺点
- 如果生产环境里的
ApiAuthRequest本来就该实现这个接口,那测试里的临时类就和真实类脱节,测试场景不够真实 - 要是后续接口新增了方法,测试里的临时类会因为没实现新方法报错,得同步更新
更规范的替代方案
方案1:让生产类实现接口(推荐)
如果生产环境的ApiAuthRequest本就应该符合HasModelSystemRestriction接口的要求,直接修改生产类让它实现接口就行,这样测试不用搞临时类,更贴近真实运行场景:
// 生产代码中的ApiAuthRequest类 class ApiAuthRequest implements HasModelSystemRestriction { // 实现接口要求的方法 public function getModel() { // 生产环境的业务逻辑 } }
之后测试里直接Mock真实类,不用额外定义临时类。
方案2:用MockBuilder强制Mock对象实现接口
如果暂时没法修改生产类,也可以通过MockBuilder让Mock对象直接实现接口,不用临时定义类:
用PHPUnit的写法:
public function factory_returns_correct_instance(AllowedHttpMethod $httpMethod): void { $request = $this->getMockBuilder(ApiAuthRequest::class) ->setImplements(HasModelSystemRestriction::class) ->getMock(); $request->method('getModel')->willReturn($this->model); $restrictor = ModelRestrictionFactory::create($request, $httpMethod); $this->assertInstanceOf(ModelSystem::class, $restrictor); }
或者用Mockery的写法:
public function factory_returns_correct_instance(AllowedHttpMethod $httpMethod): void { $request = Mockery::mock(ApiAuthRequest::class, HasModelSystemRestriction::class); $request->shouldReceive('getModel')->andReturn($this->model); $restrictor = ModelRestrictionFactory::create($request, $httpMethod); $this->assertInstanceOf(ModelSystem::class, $restrictor); }
总结
你当前的方法完全可以用,适合快速验证逻辑;但如果是需要长期维护的测试,优先推荐让生产类实现接口,或者用MockBuilder的方式,这样测试场景更真实,后续维护也更省心。
内容的提问来源于stack exchange,提问作者csandreas1
相关产品推荐
相关产品推荐

