我需要类似于C#NUnit TestCase的方案,并具有固定的预期结果。
我已经在SO上找到了此question,它具有很好的解决方案,但它们仅适用于Java,并且正如我遵循的this tutorial的一些答案中所建议的那样,但是仅将其转换为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参数化单元测试的正确方法是什么?
答案 0 :(得分:1)
我知道您正在使用JUnit 4,但是如果您考虑更新到JUnit 5,则可以使用@TestFactory
批注执行参数化的单元测试。
在您的情况下,将导致这样的测试类:
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.TestFactory
internal class EmailIdValidatorTest {
@TestFactory
fun `test email id validity`() =
listOf(
"mary@testdomain.com" to true,
"mary.smith@testdomain.com" to true,
"mary_smith123@testdomain.com" to true,
"mary@testdomaindotcom" to false,
"mary-smith@testdomain" to false,
"testdomain.com" to false
).map {
dynamicTest("email ${it.first} should be ${if (it.second) "valid" else "not valid" }") {
val actual = EmailIdUtility.isValid(it.first)
assertEquals(expected, actual)
}
}
}
答案 1 :(得分:0)
在this amazing教程之后,我们可以通过以下方式在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()
}
}
}
请记住在
@JvmStatic
方法中添加data()
,否则会出现错误:java.lang.Exception:类com.example.testapp.dev.EmailIdValidatorTest <上没有公共静态参数方法/ p>
便捷之路
如果您可以使用另一个库(也可以在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,这是lot easier 但是如果您不这样做,目前Android测试不支持JUnit 5 也使用Android-JUnit 5。