为什么这不模拟日志记录调用?

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');

由此产生两个问题:

  1. 首先,为什么我的测试没有发现我模拟了方法调用这一事实?
  2. 当需要测试这个特定方法时,您如何模拟全局函数? 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);