zoukankan      html  css  js  c++  java
  • PHPunit 测试私有方法

    This article is part of a series on testing untestable code:

    No, not those privates. If you need help with those, this book might help.

    One question I get over and over again when talking about Unit Testing is this:

    "How do I test the private attributes and methods of my objects?"

    Lets assume we have a class Foo:

    <?php
    class Foo
    {
        private $bar = 'baz';
     
        public function doSomething()
        {
            return $this->bar = $this->doSomethingPrivate();
        }
     
        private function doSomethingPrivate()
        {
            return 'blah';
        }
    }
    ?>

    Before we explore how protected and private attributes and methods can be tested directly, lets have a look at how they can be tested indirectly.

    The following test calls the testDoSomething() method which in turn calls thedoSomethingPrivate() method:

    <?php
    class FooTest extends PHPUnit_Framework_TestCase
    {
        /**
         * @covers Foo::doSomething
         * @covers Foo::doSomethingPrivate
         */
        public function testDoSomething()
        {
            $foo = new Foo;
            $this->assertEquals('blah', $foo->doSomething());
        }
    }
    ?>

    The test above assumes that testDoSomething() only works correctly whentestDoSomethingPrivate() works correctly. This means that we have indirectly testedtestDoSomethingPrivate(). The problem with this approach is that when the test fails we do not know directly where the root cause for the failure is. It could be in eithertestDoSomething() or testDoSomethingPrivate(). This makes the test less valuable.

    PHPUnit supports reading protected and private attributes through thePHPUnit_Framework_Assert::readAttribute() method. Convenience wrappers such asPHPUnit_Framework_TestCase::assertAttributeEquals() exist to express assertions onprotected and private attributes:

    <?php
    class FooTest extends PHPUnit_Framework_TestCase
    {
        public function testPrivateAttribute()
        {
            $this->assertAttributeEquals(
              'baz',  /* expected value */
              'bar',  /* attribute name */
              new Foo /* object         */
            );
        }
    }
    ?>

    PHP 5.3.2 introduces the ReflectionMethod::setAccessible() method to allow the invocation of protected and private methods through the Reflection API:

    <?php
    class FooTest extends PHPUnit_Framework_TestCase
    {
        /**
         * @covers Foo::doSomethingPrivate
         */
        public function testPrivateMethod()
        {
            $method = new ReflectionMethod(
              'Foo', 'doSomethingPrivate'
            );
     
            $method->setAccessible(TRUE);
     
            $this->assertEquals(
              'blah', $method->invoke(new Foo)
            );
        }
    }
    ?>

    In the test above we directly test testDoSomethingPrivate(). When it fails we immediately know where to look for the root cause.

    I agree with Dave Thomas and Andy Hunt, who write in their book "Pragmatic Unit Testing":

    "In general, you don't want to break any encapsulation for the sake of testing (or as Mom used to say, "don't expose your privates!"). Most of the time, you should be able to test a class by exercising its public methods. If there is significant functionality that is hidden behind private or protected access, that might be a warning sign that there's another class in there struggling to get out."

    So: Just because the testing of protected and private attributes and methods is possible does not mean that this is a "good thing".

  • 相关阅读:
    php去除字符串(空格,换行,反斜杠)
    周末撸了个Excel框架,现已开源,yyds!!
    Python基础之pytest参数化
    解决 remote: HTTP Basic: Access denied Authentication failed for 'https://'报错
    删除上传 github 中的 .idea 文件夹
    Nacos配置管理最佳实践
    痞子衡嵌入式:在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法
    痞子衡嵌入式:我入选了2021年度与非网(eefocus)星选创作者Top10
    《痞子衡嵌入式半月刊》 第 47 期
    重新iviewUI Modal 组件 ok事件默认直接关闭modal 的行为[Code Snippet]
  • 原文地址:https://www.cnblogs.com/liuguanghuiyes/p/2272429.html
Copyright © 2011-2022 走看看