測試元素或元素系統時,請個別測試。舉例來說,如果要測試 ViewModel,您不需要啟動模擬器並啟動 UI,因為 ViewModel 不會 (或不應) 依賴 Android 架構。
不過,測試的對象可能依賴其他對象才能運作。舉例來說,ViewModel 可能會依賴資料存放區才能運作。
當您需要為受測試的主體提供依附元件時,常見做法是建立測試替身 (或測試物件)。測試影本是看起來和應用程式中的元件一樣,但會在測試中建立,以提供特定行為或資料的物件。主要優點是可讓測試更快速、更簡單。
測試雙胞胎的類型
測試雙胞胎有以下幾種類型:
假 | 測試雙重代理程式,具有類別的「可用」實作項目,但實作方式適合測試,但不適合用於實際工作環境。 範例:記憶體內資料庫。 假資料不需要模擬架構,且體積輕巧。這是首選做法。 |
---|---|
模擬 | 測試雙胞胎會以您程式設計的行為運作,並且對其互動方式有預期。如果模擬資料的互動行為不符合您定義的條件,測試就會失敗。模擬資料通常會使用模擬架構建立,以便達成上述所有目標。 範例:驗證資料庫中的方法是否只呼叫一次。 |
空白 | 測試雙胞胎會按照您程式設計的行為運作,但不會對其互動方式有任何期待。通常是使用模擬架構建立。為求簡單,建議使用假資料,而非虛擬資料。 |
Dummy | 傳遞但未使用的測試影本,例如您只需要將其做為參數提供。 範例:傳遞做為點擊回呼的空白函式。 |
間諜 | 實體物件的包裝函式,可用於追蹤一些額外資訊,類似模擬物件。通常會避免使用這些函式,以免增加複雜度。因此,假的實作或模擬比間諜更為理想。 |
Shadow | 在 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)
}
在單元測試中,只要是測試人員建立的 ViewModel,就能輕鬆將 UserRepository
替換為假資料。不過,在大型測試中替換任意元素可能相當困難。
取代元件和插入依附元件
如果測試無法控制測試系統的建立作業,則替換測試替身的元件會變得更複雜,而且應用程式的架構必須遵循可測試的設計。
即使是大型端對端測試,也可以透過使用測試替身來發揮效益,例如在應用程式中瀏覽完整使用者流程的設備測試。在這種情況下,您可能需要讓測試密封。密封測試可避免所有外部依附元件,例如從網際網路擷取資料。這有助於提升可靠性和效能。
您可以自行設計應用程式,以便手動實現這種彈性,但我們建議您使用 Hilt 等依附元件插入架構,在測試期間取代應用程式中的元件。請參閱 Hilt 測試指南。
後續步驟
「測試策略」頁面說明如何使用不同類型的測試來提高工作效率。