【问题标题】:best way to mock a global static method模拟全局静态方法的最佳方法
【发布时间】:2015-03-06 20:59:50
【问题描述】:

我的应用程序有一个带有签名的记录器库:

final class Logger {
  public static method debug($msg);
  public static method warn($msg);
  public static method error($msg);
}

我要测试的类,另一个全局静态助手,用作

final class TestMe {
  public static method TestThis(){
    Logger::debug('TestThis() called');
    doThings();
  }
}

如何通过模拟Logger 类并等待预期消息来测试TestMe 类?

【问题讨论】:

  • 如果你可以重写,或者至少为了未来的开发,可以通过使用非静态类的静态实例来获得可测试性。您应该能够注入 Logger,并且此 logger 不应具有静态方法,因此可以对其进行模拟。作为最后的手段尝试github.com/Codeception/AspectMock

标签: php unit-testing testing phpunit


【解决方案1】:

您的 Logger 类不能被 PHPUnit 模拟,原因有两个。

  1. 该类被列为final,这意味着它不能被扩展。当 PHPUnit 创建一个对象的模拟时,它会创建一个扩展被模拟的类的新对象。 final 关键字阻止扩展类,因此无法创建模拟。
  2. 您要替换的方法被静态调用。您无法替换它们,因为呼叫被定向到实际班级。 PHPUnit 5.3 has a way of "mocking" static methods but that is only within the class being called statically. 它不会替代来自课堂外的调用。

http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

你有两个选项来测试这样的东西:

  1. 扩大您正在测试的行为的范围。断言无论Logger 类正在做什么都会完成。这将使任何测试不再是“单元”测试,但它们确实封装了预期的行为并且仍然有用。
  2. 重构你的用法以使用依赖注入,这样你就可以传入一个不会静态调用方法的mockLogger。这可能会更痛苦,但会使您的代码更加灵活 IMO。

【讨论】:

    【解决方案2】:

    如果您使用像 PHPUnit 这样的测试框架,它提供了模拟对象的能力。您可以为您的记录器类创建一个模拟对象并在其中定义调试方法。

    这里有详细解释:

    https://phpunit.de/manual/current/en/test-doubles.html

    这是从该页面中获取的一个小例子:

    <?php
    require_once 'SomeClass.php';
    
    class StubTest extends PHPUnit_Framework_TestCase
    {
        public function testStub()
        {
            // Create a stub for the SomeClass class.
            $stub = $this->getMockBuilder('SomeClass')
                         ->getMock();
    
            // Configure the stub.
            $stub->method('doSomething')
                 ->willReturn('foo');
    
            // Calling $stub->doSomething() will now return
            // 'foo'.
            $this->assertEquals('foo', $stub->doSomething());
        }
    }
    ?>
    

    【讨论】:

    • 当我在模拟生成器上为静态类调用 -&gt;method() 时,它失败了,说没有这样的方法。
    • 刚刚在手册上注意到这一点:Limitations Please note that final, private and static methods cannot be stubbed or mocked.
    • 这不适用于问题想要的静态方法。
    猜你喜欢
    • 2011-09-26
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    相关资源
    最近更新 更多