【问题标题】:How to write PHP Unit Test for Static Methods如何为静态方法编写 PHP 单元测试
【发布时间】:2019-06-12 20:21:25
【问题描述】:

我对 PHP 单元测试非常陌生。我正在尝试为以下功能创建单元测试:

    $context = $args[0];

    if (Subscriber::instance()->isSubscriber()) {
        $context['body_class'] .= ' ' . $this->bodyClass;
    }

    return $context;

如果用户是订阅者,那么在数组中添加类名非常简单。订阅者是具有返回真或假的静态实例方法的类。

到目前为止,我已经写了这个,但我认为这是不正确的:

$subscriber = $this->getMockBuilder(Subscriber::class)
    ->disableOriginalConstructor()
    ->setMethods(['isSubscriber'])
    ->getMock();

$subscriber->expects($this->once())
    ->method('isSubscriber')
    ->will($this->returnValue(true));

$this->assertInternalType('bool',$subscriber->isSubscriber());

任何帮助将不胜感激。

【问题讨论】:

    标签: phpunit


    【解决方案1】:

    是的,您可以使用 PhpUnitMockery 来模拟 PHP 静态方法!

    案例:待测类Foo(Foo.php)使用ToBeMocked类的静态方法mockMe

    <?php
    
    namespace Test;
    
    use  Test\ToBeMocked;
    
    class Foo {
    
        public static function bar(){
            return 1  + ToBeMocked::mockMe();        
        }
    }
    

    ToBeMocked 类 (ToBeMocked.php)

    <?php
    
    namespace Test;
    
    class ToBeMocked {
    
        public static function mockMe(){
            return 2;                
        }
    }
    

    PhpUnit 测试文件 (FooTest.php) 模拟静态方法(使用 Mockery):

    <?php
    
    namespace Test;
    
    use Mockery;
    use Mockery\Adapter\Phpunit\MockeryTestCase;
    
    // IMPORTANT: extends MockeryTestCase, NOT EXTENDS TestCase
    final class FooTest extends MockeryTestCase 
    {
        protected $preserveGlobalState = FALSE; // Only use local info
        protected $runTestInSeparateProcess = TRUE; // Run isolated
    
        /**
         * Test without mock: returns 3
         */
        public function testDefault() 
        {
    
            $expected = 3;
            $this->assertEquals(
                $expected,
                Foo::bar()
            );
        }
    
         /**
         * Test with mock: returns 6
         */
        public function testWithMock()
        {
            // Creating the mock for a static method
            Mockery::mock(
            // don't forget to prefix it with "overload:"
            'overload:Geko\MVC\Models\Test\ToBeMocked',
            // Method name and the value that it will be return
            ['mockMe' => 5]
        );
            $expected = 6;
            $this->assertEquals(
                $expected,
                Foo::bar()
            );
        }
    }
    

    运行此测试:

    $ ./vendor/phpunit/phpunit/phpunit -c testes/phpunit.xml --filter FooTest
    PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
    
    Runtime:       PHP 8.0.3
    Configuration: testes/phpunit.xml
    
    ..                                                                  2 / 2 (100%)
    
    Time: 00:00.068, Memory: 10.00 MB
    
    OK (2 tests, 3 assertions)
    

    【讨论】:

      【解决方案2】:

      您可以测试(断言)静态方法,但不能在 PHPunit 中模拟或存根它们。

      来自documentation

      请注意,final、private 和 static 方法不能被存根 或嘲笑。 PHPUnit 的测试双重功能会忽略它们,并且 保留其原始行为,静态方法除外 替换为抛出 a 的方法 \PHPUnit\Framework\MockObject\BadMethodCallException exception.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-11
        • 1970-01-01
        • 1970-01-01
        • 2011-08-23
        • 1970-01-01
        相关资源
        最近更新 更多