PHP单元测试Mock重载
2022-07-23 21:56:39

这篇博客主要是为了分享和记录一下自己在写单元测试时候遇到的一个问题。这周写的某个需求需要分析微博博文的情绪类型,用到了阿里云的nlp的sdk。然后我需要集成到公司的私有sdk里方便在各个项目里使用。

使用现成的sdk倒是没什么难度,但是在写sdk的单元测试的时候遇到问题了,本身sdk就是发http请求获取响应,但是不知道为什么用Laravel官方的Http::fake()模拟方法不顶用,依旧发出去了真实的请求,这样单元测试是无法通过的,因为用的都是测试数据,需要模拟响应看返回的数据是否符合预期。

代码大致如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Client {
public function some_nlp_api(tring $text)
{
$config = new Config();
$config->text = $text;
$client = new NlpClient();
$response = $client->emotion($text);
return $response->body;
}
}

class ClientTest{
public function test_some_nlp_api()
{
Http::fake(["*"=>Http::reponse(['foo'=>'bar'])]);
$client = new Client();
$result = $client->some_nlp_api('test');
$this->assertTrue(['foo'=>'bar'] == $result); // 请求一直发出去了导致测试一直不通过
}
}

后来想起Mock有个重载的操作,可以解决依赖让你只关注当前测试的方法而不用去关注其他不相关的方法。使用方法如下

1
2
3
4
5
6
7
8
9
10
class ClientTest{
public function test_some_nlp_api()
{
$mock = Mock::mock('overload:'.NlpClient::class); // 重载NlpClient类
$mock->shouldReceive('emotion')->andReturn(['foo'=>'bar']); //设置需要模拟的方法以及设置模拟返回数据
$client = new Client();
$result = $client->some_nlp_api('test');
$this->assertTrue(['foo'=>'bar'] == $result); // 这样这个方法就被彻底模拟了
}
}

特此记下来避免下次写单元测试的时候忘记了,顺便加强下自己的记忆!