PHPUnit中Mock对象调用方法抛出BadMethodCallException问题排查
解决PHPUnit Mock调用create方法时的BadMethodCallException问题
兄弟,这个异常基本是Mock对象不知道该怎么处理create方法的调用导致的,我给你梳理几个最常见的坑和对应的解决办法:
1. 你Mock的目标类/接口根本没有create这个公共方法
先检查你要Mock的类或接口:
- 如果是接口,确认它是否定义了
public function create(...)方法; - 如果是类,确认
create是公共方法(PHPUnit默认只能Mock公共方法,私有/受保护方法需要额外配置); - 还要注意方法名的拼写和大小写——虽然PHP方法名本身大小写不敏感,但PHPUnit的
method()方法是区分大小写的,比如你Mock时写的是method('Create'),但实际调用的是$mock->create(),就会触发异常。
2. 没有给Mock对象设置create方法的调用预期
当你调用Mock对象的方法时,PHPUnit要求你提前声明这个方法会被调用,否则就会抛出这个异常。举个例子,你需要这样配置:
// 假设你Mock的是YourClass类 $mock = $this->getMockBuilder(YourClass::class) ->disableOriginalConstructor() ->getMock(); // 必须添加这部分,告诉Mock对象如何处理create方法的调用 $mock->expects($this->any()) // 可根据测试需求改成once()、exactly(2)等 ->method('create') ->willReturn($yourExpectedReturnValue); // 也可以用willThrowException()设置异常返回
如果你的测试不需要关心create的返回值,至少也要用->willReturn(null)或者->will($this->returnSelf())(如果是链式调用场景)来设置基本预期。
3. 部分Mock时没正确指定要Mock的方法
如果你用的是部分Mock(只想Mock某个方法,其他方法调用原逻辑),要确保把create方法加入到要Mock的方法列表里:
$mock = $this->getMockBuilder(YourClass::class) ->disableOriginalConstructor() ->setMethods(['create']) // 这里必须包含create,否则会调用原类的create方法 ->getMock();
要是没加的话,Mock对象会尝试调用原类的create方法,若原方法的依赖没准备好,也可能触发异常,但如果是BadMethodCallException,更大概率是前面两种情况导致的。
4. 误Mock了错误的类/父类
检查一下你Mock的是不是你实际要测试的依赖类——比如你本来要MockUserRepository,结果Mock成了BaseRepository,而后者压根没有create方法,调用时自然会报错。
你可以对照这几点排查,一般都是前两种情况导致的问题。
内容的提问来源于stack exchange,提问作者Raheel
相关产品推荐
相关产品推荐

