PHPUnit:初始化设置后重新定义Mock的行为
在PHPUnit中重新定义已初始化Mock的行为
嘿,刚好我之前也遇到过一模一样的场景——用辅助函数封装Mock的基础配置,然后在单个测试里按需调整行为,完全没问题!下面给你几种实用的方法:
1. 直接覆盖或新增方法预期
一旦你通过mockTransport()拿到Mock实例,就可以像初始化时那样,再次调用expects()->method()来修改它的行为。PHPUnit允许你对同一个Mock对象多次设置方法预期:后续的配置会覆盖之前针对相同方法+相同匹配条件的预期,不同的方法或者不同参数匹配的预期则可以共存。
举个实际的例子:
// 先获取基础配置好的Mock $mockClient = $this->mockTransport(); // 重新定义get方法的行为:针对特定URL返回成功响应 $mockClient->expects($this->once()) ->method('get') ->with('/api/user/123') ->willReturn(new Response(200, [], '{"id":123,"name":"Gordon"}')); // 甚至可以新增其他方法的预期,比如post $mockClient->expects($this->once()) ->method('post') ->with('/api/user', ['name' => 'New User']) ->willReturn(new Response(201, [], '{"id":456}'));
2. 重置Mock的所有预期
如果你想完全清空之前的基础配置,从零开始定义行为,可以调用resetMock()方法清除所有已设置的预期,然后重新配置:
$mockClient = $this->mockTransport(); $mockClient->resetMock(); // 清除辅助函数里的所有默认预期 // 现在可以设置全新的行为 $mockClient->expects($this->exactly(2)) ->method('delete') ->willReturn(new Response(204));
3. 完整测试类示例
为了更清晰,给你看一个包含辅助函数和测试方法的完整结构:
use PHPUnit\Framework\TestCase; class YourClientTest extends TestCase { private function mockTransport(): HTTPClient { $mock = $this->getMockBuilder(HTTPClient::class) ->disableOriginalConstructor() ->getMock(); // 基础默认配置:任意调用get都返回空200响应 $mock->expects($this->any()) ->method('get') ->willReturn(new Response(200, [], '')); return $mock; } public function testFetchExistingUser() { $mockClient = $this->mockTransport(); // 覆盖get方法的行为,针对用户ID返回具体数据 $mockClient->expects($this->once()) ->method('get') ->with('/api/user/123') ->willReturn(new Response(200, [], '{"id":123,"name":"Gordon"}')); $client = new YourClient($mockClient); $user = $client->getUser(123); $this->assertEquals('Gordon', $user['name']); } public function testFetchNonExistentUserThrowsError() { $mockClient = $this->mockTransport(); // 重新定义get方法返回404 $mockClient->expects($this->once()) ->method('get') ->with('/api/user/999') ->willReturn(new Response(404, [], '')); $client = new YourClient($mockClient); $this->expectException(UserNotFoundException::class); $client->getUser(999); } }
关键注意点
- 如果你在辅助函数里用了
$this->any(),后续设置更严格的调用次数(比如once())会覆盖之前的预期,也就是说该方法必须符合新的调用次数要求。 - 确保每个测试方法都调用
mockTransport()获取新的Mock实例,避免测试之间的状态污染。
内容的提问来源于stack exchange,提问作者GordonM
相关产品推荐
相关产品推荐

