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

时间:2016-02-02 06:10:43

标签: php unit-testing mocking laravel-5.2

所以我不确定我做错了什么,但是:

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

接受它并不模拟方法调用,而是因为错误而吓坏了:

1) DetailsTest::testDetailsDoesNotReturnFalse
Error: Call to undefined function EveOnline\Logging\storage_path()

现在这个方法:storage_path是一个laravel方法,因为这个库不在laravel的一边,出于开发目的,该方法不存在,因此我试图模拟调用:{{ 1}}

由此产生两个问题:

  1. 首先,为什么我的测试没有得到我嘲笑方法调用的事实?
  2. 当它有时间测试这个特定的方法时,你如何模拟全局函数? Laravel有一些,我需要嘲笑$eveLog->requestLog($response, 'eveonline_item_details.log');方法。
  3. 思想吗

    更新

    应该知道,这个类通过一个提供者类和一个外观类变成了一个laravel外观,它们都被laravel注册,允许我做类似的事情

    storage_path

    例如。点击此处了解详情https://laravel.com/docs/5.1/facades

    我可以发布门面和提供者类,这将有所帮助。

    这个类在我耳边实例化的唯一原因是因为这个特定的组件被构建为laravel的一个单独的可安装组件。

1 个答案:

答案 0 :(得分:1)

您的方法Details::details()不知道$eveLog应该是您的模拟实例,而不是类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());

将真实的Eventlogger(类EveLogHandler的实例)注入类Details的实例。

在你的TestCase中,你现在将注入你的模拟:

$logger = $this->getLogMock();
$logger->expects($this->exactly(1))
       ->method('requestLog')
       ->with('request', 'request.log');

$details = new EveOnline\Items\Details($logger);