开发者

PHPUnit best practice for fixation of value returned by protected method?

consider the following code as PHP-style pseudo code to get my 开发者_Python百科point across.

class C extends PHPUnit_Framework_TestCase
{
  public function m1()
  {
    $v = $this->m2();

    if($v == "x")
    {
      throw new Exception();
    }
  }

  protected function m2()
  {
    [...];

    return $v;
  }
}

now I want to add a test that asserts that an Exception is thrown if m2() returns "x".

How can I simulate that?

I thought about using Reflection to redefine the method during runtime, but it seems that Reflection doesn't offer such a functionality and I would have to resort to experimental extensions like classkit or runkit. Would that be the way to go?

In this case I could extend the class and redefine m2() but where would I put that derived class then? In the same file as the test?

The latter solution wouldn't work anymore if I would choose m2 to be private.

I'm quite sure that there is a best practice to deal with this situation.


Ether I'm completely off on what you are trying to do here or you are doing something that confuses me greatly.

To me is seems that you are asking for is that you want to check that your test method throws an exception.

class C extends PHPUnit_Framework_TestCase

Why would you want to test your test method?


I'm going to assume that that is the real class and not your test

In that case I always strongly argue for just testing it as if the protected method would be inline in the public method.

You want to test the external behavior of your class. Not the implementation. The protected method is and implementation detail that your test shouldn't care about. That would mean that you would have to change your test when you change that protected method.

And from there on out:

class CTest extends PHPUnit_Framework_TestCase {

     public function testM1NormalBehavior() {

     }

     /**
      * @expectedException YourException
      */
     public function testM1ThrowsExceptionWhenM2ConditionsAreMet() {
         $c = new C('set_Up_In_A_Way_That_Makes_M2_Return_X');
         $c->m1();
     }

}


You can use a partial mock of C to force m2() to return "x". I'll assume that the extends PHPUnit_Framework_TestCase was accidental and that C is actually the class under test and not the unit test itself.

class CTest extends PHPUnit_Framework_TestCase {
    /**
     * @expectedException Exception
     */
    function testM1ThrowsExceptionWhenM2ReturnsX() {
        $c = $this->getMock('C', array('m2'));
        $c->expects($this->once())->method('m2')->will($this->returnValue('x'));
        $c->m1();
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜