模拟方法不从测试局部变量

时间:2017-07-25 13:09:05

标签: android unit-testing mockito kotlin

我已经编写了一个测试来检查我在userdata首选项方法中添加和减去硬币的方法是否正常工作。我模拟了SharedPreferences类,我使用了存储硬币数量的局部变量coins

然而,模拟的getInt()似乎没有返回正确的硬币值: 运行测试 addCoinValid 失败(预期:5,实际:0)。我在测试过程中输出了2个输出:

变量:1 - mockedReturn:0
变量:5 - mockedReturn:0

左边的数字是变量的值,右边的数字是被模拟的 getInt()返回的数字。

谁能告诉我发生了什么事? :o

这是我的测试:

class UserDataTest {
    var coins = 0

    val editor = mock<SharedPreferences.Editor>()
    val sharedPrefs = mock<SharedPreferences> {
        on{ getInt("coins", 0) } doReturn coins
        on { edit() } doReturn editor
    }
    val context = mock<Context> {
        on { getSharedPreferences("userdata", 0) } doReturn sharedPrefs
    }
    val userData = UserData(context)

    @Before
    fun initEditorMock() {
        whenever(editor.clear()).thenReturn(editor)
        whenever(editor.putInt(eq("coins"), any<Int>())).thenAnswer{ invocation ->
            this.coins = invocation.getArgument(1)
            return@thenAnswer editor
        }
    }

    @Test
    fun addCoinValid() {
        userData.setCoins(1)
        println("variable: "+coins+" - mockedReturn: "+userData.getCoins())

        userData.addCoins(5)
        println("variable: "+coins+" - mockedReturn: "+userData.getCoins())
        assertEquals(5, userData.getCoins())
    }
    // ...
}

这是经过测试的课程:

class UserData(context: Context) {
    val settings = context.getSharedPreferences("userdata", 0)

    fun getCoins(): Int {
        return settings.getInt("coins", 0)
    }

    fun setCoins(number: Int) {
        settings.edit().clear().putInt("coins", number).apply()
    }

    fun addCoins(number: Int) {
        if(number < 0) {
            return
        }
        var coins = settings.getInt("coins", 0)
        setCoins(coins+number)
    }
}

1 个答案:

答案 0 :(得分:3)

当您使用doReturn coins时,Mockito会保存coins在模拟设置时的值,即其初始值0,然后返回保存的值,忽略改变实际变量。

要在每次调用函数时使模拟查询变量,请使用doAnswer { ... }

on { getInt("coins", 0) } doAnswer { coins }