为什么这不模拟日志记录调用?
Why doesn't this mock the logging call?
所以我不确定我做错了什么但是:
class Details {
public function details($href) {
$client = new Client();
$eveLog = new EveLogHandler();
$response = $client->request('GET', $href);
$eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
我想嘲笑这个:$eveLog->requestLog($response, 'eveonline_item_details.log');
所以我写了一个测试:
class DetailsTest extends \PHPUnit_Framework_TestCase {
public function getLogMock() {
return $this->getMockBuilder('EveOnline\Logging\EveLogHandler')
->setMethods(['requestLog'])
->getMock();
}
public function testDetailsDoesNotReturnFalse() {
$details = new EveOnline\Items\Details();
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$response = $details->details('http://example.com');
$this->assertNotFalse($response);
}
}
Accept 它不会模拟方法调用,而是会因错误而崩溃:
1) DetailsTest::testDetailsDoesNotReturnFalse
Error: Call to undefined function EveOnline\Logging\storage_path()
现在这个方法:storage_path
是一个 laravel 方法,因为这个库在 laravel 之外,出于开发目的,这个方法不存在,所以我尝试模拟调用:$eveLog->requestLog($response, 'eveonline_item_details.log');
由此产生两个问题:
- 首先,为什么我的测试没有发现我模拟了方法调用这一事实?
- 当需要测试这个特定方法时,您如何模拟全局函数? Laravel 有一些,我需要模拟
storage_path
方法。
想法?
更新
应该知道,这个 class 通过提供商 class 变成了一个 laravel 门面,并且在 [=58] 注册了一个门面 class =] 允许我做类似
的事情
EveDetails::details()
例如。在这里了解更多 https://laravel.com/docs/5.1/facades
我可以 post 外观和提供者 class 会有帮助。
在我耳边实例化 class 的唯一原因是因为这个特定组件被构建为 laravel 的单独可安装组件。
您的方法 Details::details()
不知道 $eveLog
应该是您模拟的实例而不是 class EveLogHandler
。您必须使用 dependency injection.
注入记录器的实例
最简单的方法是将其放入构造函数中:
class Details {
private $eveLog;
public function __construct($eveLog) {
$this->eveLog = $eveLog;
}
public function details($href) {
$client = new Client();
$response = $client->request('GET', $href);
$this->eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
在您的生产代码中,您必须调用:
$details = new EveOnline\Items\Details(new EveLogHandler());
将真正的事件记录器(class EveLogHandler
的实例)注入到 class Details
的实例。
在您的 TestCase 中,您现在将注入模拟:
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$details = new EveOnline\Items\Details($logger);
所以我不确定我做错了什么但是:
class Details {
public function details($href) {
$client = new Client();
$eveLog = new EveLogHandler();
$response = $client->request('GET', $href);
$eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
我想嘲笑这个:$eveLog->requestLog($response, 'eveonline_item_details.log');
所以我写了一个测试:
class DetailsTest extends \PHPUnit_Framework_TestCase {
public function getLogMock() {
return $this->getMockBuilder('EveOnline\Logging\EveLogHandler')
->setMethods(['requestLog'])
->getMock();
}
public function testDetailsDoesNotReturnFalse() {
$details = new EveOnline\Items\Details();
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$response = $details->details('http://example.com');
$this->assertNotFalse($response);
}
}
Accept 它不会模拟方法调用,而是会因错误而崩溃:
1) DetailsTest::testDetailsDoesNotReturnFalse
Error: Call to undefined function EveOnline\Logging\storage_path()
现在这个方法:storage_path
是一个 laravel 方法,因为这个库在 laravel 之外,出于开发目的,这个方法不存在,所以我尝试模拟调用:$eveLog->requestLog($response, 'eveonline_item_details.log');
由此产生两个问题:
- 首先,为什么我的测试没有发现我模拟了方法调用这一事实?
- 当需要测试这个特定方法时,您如何模拟全局函数? Laravel 有一些,我需要模拟
storage_path
方法。
想法?
更新
应该知道,这个 class 通过提供商 class 变成了一个 laravel 门面,并且在 [=58] 注册了一个门面 class =] 允许我做类似
的事情EveDetails::details()
例如。在这里了解更多 https://laravel.com/docs/5.1/facades
我可以 post 外观和提供者 class 会有帮助。
在我耳边实例化 class 的唯一原因是因为这个特定组件被构建为 laravel 的单独可安装组件。
您的方法 Details::details()
不知道 $eveLog
应该是您模拟的实例而不是 class EveLogHandler
。您必须使用 dependency injection.
最简单的方法是将其放入构造函数中:
class Details {
private $eveLog;
public function __construct($eveLog) {
$this->eveLog = $eveLog;
}
public function details($href) {
$client = new Client();
$response = $client->request('GET', $href);
$this->eveLog->requestLog($response, 'eveonline_item_details.log');
if ($response->getStatusCode() === 200) {
return json_decode($response->getBody()->getContents());
}
return false;
}
}
在您的生产代码中,您必须调用:
$details = new EveOnline\Items\Details(new EveLogHandler());
将真正的事件记录器(class EveLogHandler
的实例)注入到 class Details
的实例。
在您的 TestCase 中,您现在将注入模拟:
$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
->method('requestLog')
->with('request', 'request.log');
$details = new EveOnline\Items\Details($logger);