博客 / 詳情

返回

為你的Android添加第一個單元測試

為你的Android添加第一個單元測試

​ 續上篇《從Kotlin雙鎖單例中學習到...》,我們為這個加解密單例添加一個單元測試,繼續優化我們的代碼。從這篇你可以瞭解到:

  • Android單元測試的添加
  • 單元測試的生命週期
  • 單元測試的Mock對象
  • 斷言的使用

Andorid單元測試的添加

testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

​ 步驟1,這裏是使用junit來進行andorid的單元測試,因此在模塊的build.gradle下dependencies加入junit依賴包

​ 步驟2方式一:在對應模塊-src-test-java下,添加一個kotlin或java的類SecurityHelperTest,我這裏是kotlin的語言

​ 步驟2方式二:在需要被測試的類的代碼中,右鍵-Go To-Test,創建單測類SecurityHelperTest

單元測試的生命週期

class SecurityHelperTest{
  @Before
  fun init(){
    println("===@Beforeinitcalled===")
  }
                        
  @After
  fun clearDataForTest(){
    println("===@AfterclearDataForTestcalled===")
  }
  
  @Test
  fun testInstanceOnce(){
    println("ooo@TesttestInstance1calledooo")
  }
  
  @Test
  fun testInstanceTwice(){
    println("ooo@TesttestInstance2calledooo")
  }
  
  @Test
  fun testInstanceThird(){
    println("ooo@TesttestInstance3calledooo")
  }
}

​ 為這個單元測試類SecurityHelperTest首先添加以上代碼,我們分別使用@Before/@After/@Test三種註解到類的方法上,每個方法都會打印出不同的日誌內容,最後運行這個測試代碼。

​ 看到測試結果,3個@Test的方式依次調用,每次調用前都會執行@Before,調用後都會執行@After。知道這個生命週期之後,就可以在@Before放入公共初始化的內容,在@After放入公共銷燬的內容。

單元測試的Mock對象

var mSecurityHelper: SecurityHelper = SecurityHelper.getInstance(context)

​ 由於junit是用於進行java的單元測試,而android當中有時候需要操作到android庫當中的類(如我的加解密類當中的Context),這時候junit就無法測試了,因此我們需要mock製造一個假的上下文Context,給到這個方法作為輸入的參數使用。

testImplementation 'org.mockito:mockito-core:2.19.0'

​ 這裏採用了Mockito作為單元測試的Mock使用,在build.gradle下dependencies加入Mockito依賴包。

@RunWith(MockitoJUnitRunner::class)class 
SecurityHelperTest {    
  ...    
  context = mock(Context::class.java)
}

​ 回到我們的單元測試類SecurityHelperTest,在類開頭上方加入註解@RunWith(MockitoJunitRunner::class),這個時候就通過mock(Context::class.java)的方法mock出來一個假的上下文context使用(其他android庫的對象同理)。

斷言的使用

junit中是通過assert類來實現斷言,判斷這個測試結果是否符合預期。以下列出了一些常用方法(更多詳細可查詢assert類):

assertEquals 檢查兩個變量值是否相等
assertNotNull 檢查對象是否不為空
assertSame 檢查兩個對象是否相同
assertTrue 檢查條件為真
@RunWith(MockitoJUnitRunner::class)
class SecurityHelperTest {
    companion object {
      lateinit var context: Context        
      lateinit var mSecurityHelper1: SecurityHelper        
      lateinit var mSecurityHelper2: SecurityHelper        
      lateinit var mSecurityHelper3: SecurityHelper
    }

    @Before
    fun init() {
      println("===@Before init called===") 
      context = mock (Context::class.java) 
      mSecurityHelper1 = SecurityHelper.getInstance(context)
      mSecurityHelper2 = SecurityHelper.getInstance (context)
      mSecurityHelper3 = SecurityHelper.getInstance (context)
    }

    @Test
    fun testInstanceOnce() {
       println("ooo@Test testInstance1 calledooo") 
      assertNotNull (mSecurityHelper1)
    }

    @Test
    fun testInstanceTwice() {
      println("ooo@Test testInstance2 calledooo") 
      assertSame (mSecurityHelper1, mSecurityHelper2)
    }

    @Test
    fun testInstanceThird() {
      println("ooo@Test testInstance3 calledooo") 
      assertEquals (mSecurityHelper3.javaClass.name, mSecurityHelper2.javaClass.name)
    }

    @After
    fun clearDataForTest() {
        println("===@After clearDataForTest called===")
    }
}

​ 這裏是SecurityHelperTest的完整代碼,我們分別使用一遍assertNotNull/assertSame/assertEquals三個斷言方法,用於測試這個加解密單例代碼,第一次調用是否不為空,第二次調用是否同一個實例對象,第三次調用是否實例的類名字相等。

最後運行這個單元測試

​ 以上全部就為我們這個加解密類加入了一個單元測試的過程了,最後我們運行一遍這個單元測試,通過,沒有問題哦~


作者聯繫方式:

關於我

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.