測試元素或元素系統時,請隔離測試。舉例來說,如果要測試 ViewModel,您不需要啟動模擬器並發布 UI,因為 ViewModel 不會 (或不應) 依賴 Android 架構。
不過,測試的對象可能依賴其他對象才能運作。舉例來說,ViewModel 可能會依賴資料存放區才能運作。
當您需要為受測試的主體提供依附元件時,常見做法是建立測試替身 (或測試物件)。測試影本是看起來和應用程式中的元件一樣的物件,但會在測試中建立,以提供特定行為或資料。主要優點是可讓測試更快速、更簡單。
測試雙胞胎的類型
測試雙胞胎有以下幾種類型:
偽造 | 測試雙重代理程式,具有類別的「可用」實作項目,但實作方式適合測試,但不適合用於實際工作環境。 範例:記憶體內資料庫。 假資料不需要模擬架構,且體積輕巧。這是首選做法。 |
---|---|
模擬 | 一個測試雙重,代表您的程式碼設定運作模式,且在互動方面具有期望。如果模擬資料的互動行為不符合您定義的條件,測試就會失敗。模擬資料通常是使用模擬架構建立,以便達成上述所有目標。 範例:驗證資料庫中的方法是否只呼叫一次。 |
空白 | 一個測試雙倍的測試可正常運作,但這不會預期您的互動情形。通常是使用模擬架構建立。為求簡單,建議使用假資料,而非虛擬資料。 |
虛擬 | 傳遞但未使用的測試影本,例如您只需要將其做為參數提供。 範例:做為點擊回呼傳遞的空白函式。 |
間諜 | 實體物件的包裝函式,可用於追蹤一些額外資訊,類似模擬物件。通常會避免使用這些方法,以免增加複雜度。因此,假的實作或模擬比間諜更為理想。 |
陰影 | 在 Robolectric 中使用的假資料。 |
假使意圖
假設您想要對 ViewModel 進行單元測試,該 ViewModel 依附於名為 UserRepository
的介面,並將第一位使用者的姓名公開到 UI。您可以實作介面並傳回已知資料,藉此建立假的測試雙重。
object FakeUserRepository : UserRepository {
fun getUsers() = listOf(UserAlice, UserBob)
}
val const UserAlice = User("Alice")
val const UserBob = User("Bob")
這個假的 UserRepository
不需要依賴實際工作環境版本會使用的本機和遠端資料來源。這個檔案位於測試來源集,不會隨實際工作環境應用程式一併發布。
以下測試會驗證 ViewModel 是否正確將第一個使用者名稱公開給檢視畫面。
@Test
fun viewModelA_loadsUsers_showsFirstUser() {
// Given a VM using fake data
val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init
// Verify that the exposed data is correct
assertEquals(viewModel.firstUserName, UserAlice.name)
}
在單元測試中,您可以將 UserRepository
換成假工具,因為 ViewModel 是由測試人員建立。不過,在大型測試中替換任意元素可能相當困難。
取代元件和插入依附元件
如果測試無法控制測試系統的建立作業,則替換測試替身元件會變得更複雜,而且應用程式架構必須遵循可測試的設計。
即使是大型端對端測試,也可以透過使用測試替身來發揮效益,例如在應用程式中瀏覽完整使用者流程的設備測試。在這種情況下,您可能需要讓測試密封。密封測試可避免所有外部依附元件,例如從網際網路擷取資料。這有助於提升可靠性和效能。
您可以手動設計應用程式來達到這項彈性,但還是建議您使用 Hilt 等依附元件插入架構,在測試期間替換應用程式中的元件。請參閱 Hilt 測試指南。
後續步驟
「測試策略」頁面說明如何使用不同類型的測試來提高工作效率。