gpt4 book ai didi

php - 如何在 PHPUnit 中模拟外部 Web 请求?

转载 作者:可可西里 更新时间:2023-11-01 12:49:16 25 4
gpt4 key购买 nike

我正在为 PHP 设置测试套件 Propel项目使用 Phactory , 和 PHPUnit .我目前正在尝试对一个发出外部请求的函数,我想在模拟中 stub 对该请求的响应。

这是我要测试的类的片段:

class Endpoint {
...
public function parseThirdPartyResponse() {
$response = $this->fetchUrl("www.example.com/api.xml");
// do stuff and return
...
}

public function fetchUrl($url) {
return file_get_contents($url);
}
...

这是我正在尝试编写的测试函数。

// my factory, defined in a seperate file
Phactory::define('endpoint', array('identifier' => 'endpoint_$n');

// a test case in my endpoint_test file
public function testParseThirdPartyResponse() {
$phEndpoint = Phactory::create('endpoint', $options);
$endpoint = new EndpointQuery()::create()->findPK($phEndpoint->id);

$stub = $this->getMock('Endpoint');
$xml = "...<target>test_target</target>..."; // sample response from third party api

$stub->expects($this->any())
->method('fetchUrl')
->will($this->returnValue($xml));

$result = $endpoint->parseThirdPartyResponse();
$this->assertEquals('test_target', $result);
}

我现在可以看到,在我尝试我的测试代码之后,我正在创建一个模拟对象使用 getMock,然后再不使用它。所以函数 fetchUrl实际上执行,这是我不想要的。但我仍然希望能够使用Phactory 创建了 endpoint 对象,因为它具有所有正确的字段从我的工厂定义中填充。

有没有办法让我在现有对象上 stub 方法?所以我可以 stub fetch_url 我刚刚创建的 $endpoint 端点对象?

还是我做错了?有没有更好的方法让我进行单元测试我的功能依赖于外部网络请求?

我确实阅读了有关“Stubbing and Mocking Web Services”的 PHPUnit 文档,但是他们这样做的示例代码有 40 行长,还不包括必须定义您自己的 wsdl。我很难相信这是我处理这个问题的最方便的方法,除非 SO 的好人强烈反对。

非常感谢任何帮助,我整天都被这个挂断了。谢谢!!

最佳答案

从测试的角度来看,您的代码有两个问题:

  1. 该 url 是硬编码的,您无法为开发、测试或生产更改它
  2. 端点知道如何检索数据。从您的代码中我无法说出端点的真正作用,但如果它不是低级别的“只需获取数据”对象,它就应该不知道如何检索数据。

对于这样的代码,没有好的方法来测试您的代码。您可以使用 Reflections,更改您的代码等等。这种方法的问题是您没有测试您的实际对象,而是测试了一些反射以适应测试。

如果你想编写“好的”测试,你的端点应该是这样的:

class Endpoint {

private $dataParser;
private $endpointUrl;

public function __construct($dataParser, $endpointUrl) {
$this->dataPartser = $dataParser;
$this->endpointUrl = $endpointUrl;
}

public function parseThirdPartyResponse() {
$response = $this->dataPartser->fetchUrl($this->endpointUrl);
// ...
}
}

现在您可以注入(inject) DataParser 的 Mock,它根据您要测试的内容返回一些默认响应。

下一个问题可能是:如何测试 DataParser?大多数情况下,你没有。如果它只是 php 标准函数的包装器,则不需要。您的 DataParser 应该非常低级,看起来像这样:

class DataParser {
public function fetchUrl($url) {
return file_get_contents($url);
}
}

如果您需要或想要测试它,您可以创建一个 Web 服务,它存在于您的测试中并充当“模拟”,始终返回预配置的数据。然后,您可以调用此模拟 url 而不是真实 url 并评估返回值。

关于php - 如何在 PHPUnit 中模拟外部 Web 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11268125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com