測試不僅僅是一種確保代碼正常工作的方式,它們還有助於識別代碼異味。在你的情況下寫一個測試很難,因爲你使用靜態方法。
曾經有一個staticExpects
方法,但很久以前在phpunit中已棄用,所以這不是真的可行。使此代碼可測試的最佳方法是刪除static
關鍵字。這對getIds()
很容易,但由於靜態find()
由第三方(yii的ActiveRecord)定義,所以您無法真正刪除它。相反,你可以用非靜態方法來包裝它。通過觸及這些包裝第三方代碼的小方法,這給了您將來可以從Active Record移動到Doctrine等其他實現的好處。
一旦你這樣做,你可以創建模型的部分模擬,以確保該方法被稱爲:
class Model extends ActiveRecord
{
private $ids;
protected function findIds()
{
return static::find()->select('id')->column();
}
public function getIds()
{
if (empty($this->ids)) {
$this->ids = $this->findIds()
}
return $this->ids;
}
}
,並在您的測試:
public function testFindIdsIsCalledWhenGetterIsNotInitialized()
{
$model = $this->getMockBuilder(Model::class)
->setMethods(['findIds'])
->getMock();
$model->expects($this->once())
->method('findIds')
->will($this->returnValue([1, 2, 3]));
$ids = $model->getIds();
$this->assertEquals([1, 2, 3], $ids);
}
這應該有2種說法,一個用於預期的方法調用,另一個用於返回的值。此測試繞過活動記錄,只確保您的getIds()
方法按預期工作。正如您的問題的評論中提到的,另一種方法是使用功能測試,通過從(測試)數據庫中提取數據來實際測試數據庫交互。顯然,由於這需要數據庫連接並檢索測試數據,例如從一些以前設置的燈具,這是一個更多的工作,測試會更慢。取決於你的項目有多大,這可能不是問題,你也可以更好地測試Active Record實現中的邏輯。
每當您重複使用模型時,都會回滾到默認值? – Yerke