PHPUnit测试调用函数的次数

时间:2010-09-28 02:21:28

标签: php unit-testing testing mocking phpunit

我正在使用phpunit进行测试,我遇到了一个问题。我正在尝试测试我班上的公共功能。根据传递给方法的参数,我的测试类中的受保护函数也会被调用一次或两次。我目前有一个测试来检查返回数据是否正确,但我还想确保受保护的方法被调用正确的次数。

我知道模拟对象将允许我计算调用函数的次数,但它也会覆盖受保护函数返回的值。我尝试使用没有“will”部分的模拟对象,但它只返回null,而不是受保护方法的实际值。

ExampleClass中

public function do_stuff($runTwice){
$results = do_cool_stuff();
  if($runTwice){
    $results = 2 * do_cool_stuff();
  }
  return $results;
}

protected function do_cool_stuff()
{
  return 2;
} 

在我的测试中,我想检查do_cool_stuff()是否被调用一次或两次,但我仍然希望两个函数的返回值相同,所以我也可以在单元测试中测试它们。

TL;博士 我想计算调用我的测试对象中受保护方法的次数(就像你可以用模拟对象做的那样),但我仍然希望我的测试方法中的所有方法都返回它们的正常值(而不是像模拟对象)

2 个答案:

答案 0 :(得分:4)

或者,回到滚动您自己的可测试替身。以下是不错的,但你明白了:

class ExampleClass {
    public function do_stuff($runTwice) {
        $results = $this->do_cool_stuff();
        if ($runTwice) {
            $results = 2 * $this->do_cool_stuff();
        }
        return $results;
    }

    protected function do_cool_stuff() {
        return 2;
    }
}

class TestableExampleClass extends ExampleClass {
    /** Stores how many times the do_cool_stuff method is called */
    protected $callCount;

    function __construct() {
        $this->callCount = 0;
    }

    function getCallCount() {
        return $this->callCount;
    }

    /** Increment the call counter, and then use the base class's functionality */
    protected function do_cool_stuff() {
        $this->callCount++;
        return parent::do_cool_stuff();
    }
}


class ExampleClassTest extends PHPUnit_Framework_TestCase {

    public function test_do_stuff() {
        $example = new ExampleClass();
        $this->assertEquals(2, $example->do_stuff(false));
        $this->assertEquals(4, $example->do_stuff(true));
    }

    public function test_do_cool_stuff_is_called_correctly() {
        // Try it out the first way
        $firstExample = new TestableExampleClass();
        $this->assertEquals(0, $firstExample->getCallCount());
        $firstExample->do_stuff(false);
        $this->assertEquals(1, $firstExample->getCallCount());

        // Now test the other code path
        $secondExample = new TestableExampleClass();
        $this->assertEquals(0, $secondExample->getCallCount());
        $secondExample->do_stuff(true);
        $this->assertEquals(2, $secondExample->getCallCount());
    }
}

我想知道是否计算受保护方法的次数是否真的是一个很好的测试。它将您的测试与实现相结合非常困难。它是否被调用两次,或者你对与其他对象的交互更感兴趣,这真的很重要吗?或者这可能指向do_cool_stuff需要将重构分为两个独立的方法:

class ExampleClass {
    public function do_stuff($runTwice) {
       if ($runTwice) {
          return $this->do_cool_stuff_twice();
       } else {
          return $this->do_cool_stuff_once();
       }
    }
    //...
 }

答案 1 :(得分:1)

在使用该类之前尝试设置全局变量。

$IAmDeclaredOutsideOfTheFunction;

然后用它来存储计数,并在调用函数和类之后简单地检查它。

相关问题