首页 > 解决方案 > 如何在 JUnit 4 和 Kotlin for Android 中创建参数化测试用例?

问题描述

我需要类似于 C# NUnit TestCase场景的东西,并且具有固定的预期结果。

我已经在 SO 上找到了这个问题,它有很好的解决方案,但它们仅适用于 Java,并且正如我遵循本教程的一些答案中所建议的那样,但简单地将其转换为 Kotlin 是行不通的。

@RunWith(value = Parameterized.class)
public class EmailIdValidatorTest {

    private String emailId;
    private boolean expected;

    public EmailIdValidatorTest(String emailId, boolean expected) {
        this.emailId = emailId;
        this.expected = expected;
    }
    @Parameterized.Parameters(name= "{index}: isValid({0})={1}")
    public static Iterable<Object[]> data() {
        return Arrays.asList(new Object[][]{
                        {"mary@testdomain.com", true},
                        {"mary.smith@testdomain.com", true},
                        {"mary_smith123@testdomain.com", true},
                        {"mary@testdomaindotcom", false},
                        {"mary-smith@testdomain", false},
                        {"testdomain.com", false}
                }
        );
    }
    @Test
    public void testIsValidEmailId() throws Exception {
        boolean actual= EmailIdUtility.isValid(emailId);
        assertThat(actual, is(equalTo(expected)));
    }
}

那么用 JUnit 编写 Kotlin 参数化单元测试的正确方法是什么?

标签: androidunit-testingkotlinjunit

解决方案


按照这个惊人的教程,我们可以用这种方式用 Kotlin 语言实现它:

首先将EmailIdUtility类转换为 Kotlin:

object EmailIdUtility {
    fun isValid(email: String): Boolean {
        val regex =
            "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"
        val pattern = Pattern.compile(regex)
        val m = pattern.matcher(email)
        return m.matches()
    }
}

然后转换EmailIdValidatorTest成 Kotlin

@RunWith(value = Parameterized::class)
class EmailIdValidatorTest(
    private val email: String,
    private val expected: Boolean)
{
    @Test
    fun testIsValidEmailId() {
        val actual = EmailIdUtility.isValid(email)
        assertEquals(expected, actual)
    }

    companion object {
        @JvmStatic
        @Parameterized.Parameters(name = "{index}: isValid({0})={1}")
        fun data(): Iterable<Array<Any>> {
            return arrayListOf(
                arrayOf("mary@testdomain.com", true),
                arrayOf("mary.smith@testdomain.com", true),
                arrayOf("mary_smith123@testdomain.com", true),
                arrayOf("mary@testdomaindotcom", false),
                arrayOf("mary-smith@testdomain", false),
                arrayOf("testdomain.com", false)
            ).toList()
        }
    }
}

记得添加方法@JvmStaticdata()否则会报错:java.lang.Exception: No public static parameters method on class com.example.testapp.dev.EmailIdValidatorTest


更简单的方法

如果您可以使用另一个库(也可以在 Android 中使用),我建议您将JUnitParams添加到您的测试依赖项中,在 Android 中它可能是:

testImplementation  "pl.pragmatists:JUnitParams:1.1.1"

然后你可以用这种方式转换上面的类:

@RunWith(JUnitParamsRunner::class)
class EmailIdValidatorTest {

    @Test
    @Parameters(value = [
        "mary@testdomain.com, true",
        "mary.smith@testdomain.com, true",
        "mary_smith123@testdomain.com, true",
        "mary@testdomaindotcom, false",
        "mary-smith@testdomain, false",
        "testdomain.com, false"
    ])
    fun testIsValidEmailId(email: String, expected: Boolean) {
        val actual = EmailIdUtility.isValid(email)
        assertEquals(expected, actual)
    }
}

这对我来说比JUnit方式容易得多。

有关如何使用 JUnitParams 的更多示例,您可以查看链接。

使用 JUnit 5,这要容易 得多,但如果您也不使用Android-JUnit 5,Android 测试目前不支持 JUnit 5


推荐阅读