我正在使用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;博士 我想计算调用我的测试对象中受保护方法的次数(就像你可以用模拟对象做的那样),但我仍然希望我的测试方法中的所有方法都返回它们的正常值(而不是像模拟对象)
答案 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;
然后用它来存储计数,并在调用函数和类之后简单地检查它。