簡體   English   中英

SUT-測試內部行為TDD

[英]SUT - Testing Internal Behaviour TDD

我對測試要求有疑問。

讓我們舉個例子:

Class Article {

    public void deactive() {//some behaviour, which deactives article}

}

我有要求,可以deactived Article。 我將在我的Article類中實現它。

測試會打電話deactive的方法,但現在該怎么辦? 我需要在測試結束時檢查是否滿足要求,因此我需要實現isDeactived方法。
這是我的問題,如果我真的應該這樣做? 此方法僅在我的測試用例中使用,其他地方不使用。 所以我正在使我的類接口復雜化,只是為了確定斷言(如果確實已停用)。

什么是正確的實施方式?

通常認為可以將測試鈎子添加到類中。 最好有一個稍微混亂的界面並知道您的類是否有效,而不是使其無法測試。 但是還有其他一些解決方案。

如果可以將方法設置為受保護或私有包,則可以使用類似Guava的@VisibleForTesting注解的方法 Java以外的其他語言可能具有其他類似的庫。

您也可以從Article繼承來訪問私有字段。

class ArticleTest extends Article {
    @Test
    public void deactiveTest() {
        this.deactive();
        assertTrue(this.isDeactive);    
    }
}

所有這些都假設您有一個用於標記對象是否處於活動狀態的字段。

在某些情況下,您可能會引起一些副作用,例如調用數據庫,以及一些服務表明您正在停用該文章。 如果是這樣,您應該模擬用來產生副作用的協作者,並驗證您是否正確調用了它們。

例如(在java / mockito中為偽代碼):

@Test
public void deactiveTest() {
    Article underTest = new Article(databaseMock, httpMock); //or use dependency injection framework of your choice...
    underTest.deactive();
    verify(databaseMock).calledOnce().withParams(expectedParams);
    verify(httpMock).calledOnce().withParams(expectedParams);
}

最后的可能性是,如果該字段影響其他方法或函數的行為,則可以嘗試(再次使用偽代碼):

article.deactive()
result = article.post() // maybe returns true if active, else false?
assertFalse(result)

這樣,您正在測試結果行為,而不僅僅是檢查內部狀態。

聽起來您正在按照以下方式編寫測試:

assertThatCallingDeactiveMarksArticleAsDeactivated

使用isDeactivated方法,此測試變得很簡單,但是正如您所說的, Article類不包含此方法。 於是,問題就變成了它應該有一個方法。 答案實際上取決於deactive Article類的真正含義。

我希望並active Article不同的行為在從某種方式deactive Article 否則,狀態更改似乎沒有原因/沒有要測試的內容。

舉一個實際的例子,從Article類的客戶的角度來看它。 某些情況觸發了對deactive的調用。 它可能就像用戶單擊用戶界面上的“停用”按鈕/鏈接一樣簡單,它可以調用Article類。 在此調用之后,我希望用戶界面以某種方式反映出該Article處於非活動狀態(例如,通過使按鈕/鏈接變灰),但是要做到這一點,UI必須能夠讀取狀態Article ,這使我們回到了問題所在,即為什么當前代碼不需要isDeactivated方法?

如果不了解deactive方法的實現(它只是設置一個標志還是以一種可觀察的方式調用其他代碼)以及狀態更改如何影響Article及其客戶端的行為,就很難給出更多信息。具體的回應。

理想情況下,您不想測試方法或類的內部,因為這會使測試變得脆弱且緊密耦合。 如果您重構產品代碼,則您的測試會有較大的變化,也需要重構,因此可以從測試中受益。 您想嘗試整體測試類的行為(即調用deactivate做什么)

查看Kent Beck的4條簡單設計規則(按優先順序排列)。

1)所有測試通過

2)表達意圖

3)消除重復

4)最小元素

最后一條規則是,系統的大小不應超過所需的大小,這是您的問題所在。 鑒於這是不重要的元素,並且最好1)通過測試和2)表達意圖,(在我看來)簡單地添加isActive()方法是可以接受的。

這也使該類更加有用和通用,因為您停用了某些東西,因此能夠驗證其狀態似乎合乎邏輯。

同樣如前所述,必須具有調用deactivate的效果,該效果本身應進行測試,因此請嘗試進行測試-可能更適合放置Integration Test,或者必須模擬或存根另一個類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM