简单的存根
有时,有一些代码难以测试,例如访问数据库或与用户交互。你可以删除代码部分,以便测试其余代码。
让我们从一个提示用户的类开始。为简单起见,它只有两个方法,一个实际上提示用户(将由所有其他方法使用)和我们要测试的方法,它提示和过滤掉只有是和没有答案。请注意,此代码过于简单化以用于演示目的。
class Answer
{
// prompt the user and check if the answer is yes or no, anything else, return null
public function getYesNoAnswer($prompt) {
$answer = $this->readUserInput($prompt);
$answer = strtolower($answer);
if (($answer === "yes") || ($answer === "no")) {
return $answer;
} else {
return null;
}
}
// Simply prompt the user and return the answer
public function readUserInput($prompt) {
return readline($prompt);
}
}
要测试 getYesNoAnswer
,需要删除 readUserInput
以模仿用户的答案。
class AnswerTest extends PHPUnit_Framework_TestCase
{
public function test_yes_no_answer() {
$stub = $this->getMockBuilder(Answer::class)
->setMethods(["readUserInput"])
->getMock();
$stub->method('readUserInput')
->will($this->onConsecutiveCalls("yes","junk"));
// stub will return "yes"
$answer = $stub->getYesNoAnswer("Student? (yes/no)");
$this->assertSame("yes",$answer);
// stub will return "junk"
$answer = $stub->getYesNoAnswer("Student? (yes/no)");
$this->assertNull($answer);
}
}
第一行代码创建存根,它使用 getMockBuilder
而不是 createMock
。createMock
是使用默认值调用 getMockBuilder
的快捷方式。其中一个默认设置是删除所有方法。对于这个例子,我们想测试 getYesNoAnswer
,所以它不能被删除。getMockBuilder
调用 setMethods
来请求只删除 readUserInput
。
第二行代码创建了存根行为。它会截断 readUserInput
方法并在后续调用时设置两个返回值,yes
后跟 junk
。
第三行和第四行代码测试 getYesNoAnswer
。第一次,假人回答是并且测试的代码正确地返回是,因为它是有效的选择。第二次,假人响应垃圾,测试的代码正确返回 null。