首页 > 解决方案 > PowerMock`thenReturn`不返回模拟静态方法的预期数据?

问题描述

我能够调整我的测试,但它失败了。问题是,模拟方法仍然返回错误的数据。这是我要测试的方法:

fun getTextByLanguage(list: List<TitleModel>) : String {
    val deviceLanguage = Locale.getDefault().language

    var default = ""
    for (item in list) {
        if (item.culture.contains(deviceLanguage, true)) return item.value
        if (item.culture.contains("en", true)) default = item.value
    }

    return default

}

这就是我测试该方法的方式:

import junit.framework.TestCase.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.api.mockito.PowerMockito.*
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import java.util.Locale

@RunWith(PowerMockRunner::class)
@PrepareForTest(Locale::class)
class AppConfigUtilityByPowerMockTest {

    @Test
    fun `getTextByLanguage, test en`() {
        mockStatic(Locale::class.java)
        val mockedLocal = mock(Locale::class.java)
        `when`(Locale.getDefault()).thenReturn(mockedLocal)
        `when`(mockedLocal.language).thenReturn("en")

        val list = listOf(TitleModel("en-ca", "Home"), TitleModel("fr-ca", "HomeFr"))
        val actual = getTextByLanguage(list)

        assertEquals("Home", actual)
    }

    @Test
    fun `getTextByLanguage, test fr`() {
        mockStatic(Locale::class.java)
        val mockedLocal = mock(Locale::class.java)
        `when`(Locale.getDefault()).thenReturn(mockedLocal)
        `when`(mockedLocal.language).thenReturn("fr")

        val list = listOf(TitleModel("en-ca", "Home"), TitleModel("fr-ca", "HomeFr"))
        val actual = getTextByLanguage(list)

        assertEquals("HomeFr", actual)
    }
}

第一个测试用例没有问题,但第二个测试用例失败。这是输出:

junit.framework.ComparisonFailure: expected:<Home[Fr]> but was:<Home[]>
Expected :HomeFr
Actual   :Home

标签: androidkotlinjunit4powermock

解决方案


回答这个问题的一种方法是从方法中去掉Local类并以 Kotlin 的方式做事。所以,我所做的就是像这样改变我原来的方法:

fun getTextByLanguage(list: List<TitleModel>, deviceLanguage: String = getDeviceLanguage()) : String {
    var default = ""
    for (item in list) {
        if (item.culture.contains(deviceLanguage, true)) return item.value
        if (item.culture.contains("en", true)) default = item.value
    }

    return default
}

fun getDeviceLanguage(): String {
    return Locale.getDefault().language
}

现在我的测试类看起来像这样:

import junit.framework.TestCase.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import java.util.Locale

@RunWith(PowerMockRunner::class)
@PrepareForTest(Locale::class)
class AppConfigUtilityByPowerMockTest {

    @Test
    fun `getTextByLanguage, test en`() {
        val list = listOf(TitleModel("en-ca", "Home"), TitleModel("fr-ca", "HomeFr"))
        val actual = getTextByLanguage(list, "en")

        assertEquals("Home", actual)
    }

    @Test
    fun `getTextByLanguage, test fr`() {
        val list = listOf(TitleModel("en-ca", "Home"), TitleModel("fr-ca", "HomeFr"))
        val actual = getTextByLanguage(list, "fr")

        assertEquals("HomeFr", actual)
    }
}

虽然我的测试通过了,但我仍然愿意看到你的建议,并愿意接受你对我问题的回答。


推荐阅读