我認爲你遇到的問題是你缺少一個確保正確測試結果的設置。這聽起來可能有點奇怪,但考慮到這種情況下
class ConnectedResource
{
private $connector;
public function __construct($connector)
{
$this->connector = $connector;
}
public function connectToDevice()
{
try {
$this->connector->connect();
} catch (\Exception $e) {
return false;
}
return true;
}
}
這真的是簡化,但基本的一點是,要測試兩個路徑:connect()的成功和例外。
你會做什麼在您的測試,現在要麼是
public function testSuccessfulConnectReturnsTrue()
{
$connector = new Connector(
// config to make a successful connection
);
$myObject = new ConnectedResource($connector);
$this->assertTrue($myObject->connectToDevice());
}
public function testFailedConnectReturnsFalse()
{
$connector = new Connector(
// invalid config that will raise an exception
);
$myObject = new ConnectedResource($connector);
$this->assertFalse($myObject->connectToDevice());
}
現在這兩個測試將工作,因爲他們使用不同的連接(一個工程,一個是沒有)。
另一種可能性是通過模擬連接器。換句話說,而不是一個真正的連接器,你創建一個虛擬對象,你可以自己決定什麼$this->connector->connect()
會返回。把它看作是「假設我有一個連接器返回true,那麼ConnectedResource應該表現得如此」。該代碼,這可能是這個樣子:
public function testSuccessfulConnectReturnsTrue()
{
$connector = $this->createMock(Connector::class);
$connector->expect($this->any())
->method('connect')
->willReturn(true)
;
$myObject = new ConnectedResource($connector);
$this->assertTrue($myObject->connectToDevice());
}
以及失敗的情況會是這個樣子:
public function testFailedConnectReturnsFalse()
{
$connector = $this->createMock(Connector::class);
$connector->expect($this->any())
->method('connect')
->willReturn($this->throwException(new Exception))
;
$myObject = new ConnectedResource($connector);
$this->assertTrue($myObject->connectToDevice());
}
現在你控制測試(連接)的範圍之外的一切並且只測試connectToDevice()
中定義的行爲。這樣可以使您的測試免受其他課程中的變更的影響,但是例如在將來更新connect()函數發生變化時可能會導致問題。參數被添加或改變。
重要的是,您必須確保滿足您的測試運行要求。
唯一一次失敗的時候是你有錯誤,否則其中一個總是爲真或假。如果你在測試中有錯誤,測試不會結束(只有當你沒有發現錯誤時)。 – Edwin
@Edwin問題是我不想有幾十個應該失敗的失敗測試。此外,函數可能會拋出一個意外的異常,這將導致兩個函數都失敗,從而導致測試失敗。 – DrKey
那麼你在做錯了什麼,無論是在測試中還是在開發中。測試應該始終有效,如果你想測試失敗,只需以你確定沒有連接存在的方式設置你的環境=> connectToDevice將是錯誤的。 – Edwin