我正在測試一個對象,該對象旨在測試用戶是否擁有給定的電子郵件。因此,在調用「tryEmail」方法時,它會向給定的電子郵件地址發送帶有確認鏈接的消息。我的測試如下所示:PHPUnit:在一個測試中對模擬方法使用多個斷言是否是一種不好的做法?
public function testSendingWasSuccessful() {
$confirmationObject = $this->getMock('LT\EmailConfirmation\Model\ConfirmationObjectInterface');
$testType = 'test.type';
$testEmail = '[email protected]';
$testData = [];
// EmailTester should create a new confirmation object.
$this->manager->expects(static::once())
->method('create')->with($testType, $testEmail)
->willReturn($confirmationObject);
// Then it should send the confirmation message.
$this->mailer->expects(static::once())
->method('send')->with(static::identicalTo($confirmationObject))
->willReturn(true);
// And save the confirmation object.
$this->manager->expects(static::once())
->method('save')->with(static::identicalTo($confirmationObject));
$tester = new EmailTester($this->repository, $this->manager, $this->confirmationHandler, $this->mailer);
static::assertTrue($tester->tryEmail($testType, $testEmail, $testData));
}
現在您可以看到它可能有什麼問題 - 它包含多個斷言。爲什麼我決定在一次測試中使用這些斷言?因爲他們彼此依賴。因此,只有在創建新的確認對象時才應發送確認消息,並且只有在確認消息已發送時才應保存確認對象,最後,使用這些模擬方法的「tryEmail」方法的輸出正在斷言。
但是,我覺得我不小心只是用我的斷言描述了「tryEmail」方法的實現。但是,似乎需要對這種方法進行全面的介紹,並且確保它始終按照應有的方式工作。我可以想象如果我將刪除任何這些斷言的錯誤傳遞。例如:static::identicalTo($confirmationObject)
這基本上是:check if the object passed to the mailer is the same as the one created before
。如果我改變郵件的界面,我將不得不改變EmailTester
的這個測試,所以看起來我在這裏做錯了什麼。然而,在同一時間 - 我怎樣才能檢查上述斷言,而不引入這種耦合?或者,也許我應該離開這未經考驗?
我在做對還是錯?我怎麼能改進它?何時真的使用嘲諷斷言?
補充:我只是有一個想法 - 是不正確的,測試類應該測試實施(如果實現與接口符合)?這意味着在測試中描述實現實際上是一件好事,因爲它確保實現正確工作。這也意味着實施的耦合水平將被轉移到測試中,並且是不可避免的。我錯了嗎?
感謝您的回答!您對'LT \ EmailConfirmation \ Model \ ConfirmationObjectInterface'的評論給了我一些想法。我有意識地設計它,以儘量減少使用此對象時所需的工作量。現在我幾乎可以在控制器中使用一個函數'tryEmail'並完成。否則,我將不得不拉動管理器,並在控制器中創建確認對象,然後通過'tryEmail'方法傳遞它,這將只是我的Controller中的更多代碼,這似乎是一個壞主意。你確定這會有所改進嗎? –
我很有信心。我爲你的對象增加了靈活性,'EmailTester'現在可以採用不同類型的對象。它也讓他們專注。如果您需要發送不同的電子郵件類型,則此對象應該能夠毫無問題地處理它。 – Schleis