phpunit - 模拟外部静态方法

alo*_*jay 5 php phpunit unit-testing

我正在拼命尝试对商店系统的模块进行单元测试。该商店系统使用静态方法,我必须在我想要测试的函数中调用这些方法。

public function toTest() {
    $value = \Context::getData();
    return $value;
}
Run Code Online (Sandbox Code Playgroud)

现在我如何在模拟这个静态调用的同时对该函数进行单元测试?我尝试使用 AspectMock 但这不起作用,因为它显然需要访问原始 \Context 类,该类不可用,因为它是外部系统。我还尝试使用 class_alias 创建自己的 Context 类,但这也不起作用,因为我需要不同的 Context 输出,具体取决于我正在测试的函数。并且为不同的测试多次设置 class_alias 不起作用,因为不能多次声明同一个类,并且 @runTestsInSeparateProcesses 没有达到预期的效果。

编辑:没有一个重复项为我的情况提供了可行的解决方案,所以我认为这不是重复项。由于无法访问商店系统代码,尤其是像这样难以维护的代码,PHP 无法轻松进行单元测试。另外,我找到的解决方案应该可以帮助具有类似设置的其他人。

alo*_*jay 4

我可以使用 Mockery 库解决我的问题。我尝试了一些但没有任何效果。有了Mockery,现在一切似乎都有可能了。这个链接确实有帮助:https ://robertbasic.com/blog/mocking-hard-dependency-with-mockery/

您可以轻松模拟对不属于您的类的静态调用:

public function methodToTest() {
    return \Context::getData();
}

public function testMethodToTest() {
    m::mock('alias:\Context')
        ->shouldReceive('getData')
        ->andReturn('foo');
}
Run Code Online (Sandbox Code Playgroud)

甚至您无权访问的类的实例化:

public function methodToTest() {
    $obj = new \Category(5);
    return $obj->id;
}

public function testMethodToTest() {
    m::mock('overload:\Category')
        ->shouldReceive('__construct')
        ->with(5)
        ->andSet('id', 5);
}
Run Code Online (Sandbox Code Playgroud)

但你必须记住,你需要在类的开头添加两个 phpunit 注释:

* @runTestsInSeparateProcesses
* @preserveGlobalState disabled
Run Code Online (Sandbox Code Playgroud)