首页 文章

PHPUnit测试调用函数的次数

提问于
浏览
3

我正在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; dr我想计算调用我的测试对象中受保护方法的次数(就像你可以用模拟对象做的那样),但我仍然希望我的测试方法中的所有方法都返回它们的正常值(不是像模拟对象) .

2 回答

  • 1

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

    $IAmDeclaredOutsideOfTheFunction;
    

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

  • 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();
           }
        }
        //...
     }
    

相关问题