簡單的存根
有時,有一些程式碼難以測試,例如訪問資料庫或與使用者互動。你可以刪除程式碼部分,以便測試其餘程式碼。
讓我們從一個提示使用者的類開始。為簡單起見,它只有兩個方法,一個實際上提示使用者(將由所有其他方法使用)和我們要測試的方法,它提示和過濾掉只有是和沒有答案。請注意,此程式碼過於簡單化以用於演示目的。
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。