【发布时间】:2017-09-26 11:50:40
【问题描述】:
我想对官方 Segment PHP 集成的包装类进行单元测试。因此,我必须用 Mockery 模拟 the Segment class,这样就不会有任何真正的 API 请求。
问题
要模拟的类仅包含静态方法。因此,我尝试像这样模拟它(使用alias):
$segment = Mockery::mock('alias:Segment');
这可行,但前提是类不是由作曲家自动加载的。如果我加载它 - 就像我必须为应用程序的其余部分加载一样 - 我会收到错误
Could not load mock Segment, class already exists.
(这是有道理的,因为文档声明之前不得加载别名类。)
问题
我怎样才能模拟这个(邪恶的?)类,但仍然像往常一样在我的应用程序的其余部分使用它?
【问题讨论】:
-
如果我理解正确的话,这听起来更像是一个设计问题,而不是“如何模拟它”的问题。您引用该库的类到底是什么样的?您是以某种方式注入依赖项还是只是直接从您的方法中直接调用库?
-
我也想过这个问题,但想不出解决办法。目前,我将这些方法直接称为:
Segment::track(...)。注入类没有意义,因为它只有静态方法,不是吗? -
我认为这很有意义,因为这将允许您从测试中通过它的模拟版本。这在生产中似乎没有必要,因为它需要为您的类进行额外设置,但我认为这是使类可测试的常用方法。如果你有能力使用依赖注入容器(如PHP-DI),那将不是问题。
-
是的,额外的包装器也是一个很好的解决方案,但是您仍然必须测试该包装器并遇到同样的问题。此外,您的类已经 是 一个包装器,所以我认为这只是包装器-ception :) 这样想:您要测试的只是调用某个对象上的特定方法。做到这一点的最好方法是控制该对象是什么,并允许这样做,您只需从外部传入它,而不是在您的类中自动加载它。然后在生产环境中通过真实类,在测试用例中通过模拟。
-
嗯,我明白了。但这意味着我将注入 Segment 类的实例,然后在其上调用静态方法,例如
$segmentInstance->track(...)。我认为这是不好的做法,因为它“隐藏”了我在静态上下文中调用track(...)?
标签: php unit-testing static composer-php mockery