我在运行时对 junit 测试和 Android (ART) 的相同输入得到了不同的结果

I got different result for same input on junit tests and on Android (ART) at runtime

我有一个在目标文本上查找匹配文本的静态方法,但它 returns 相同输入的不同结果,导致 Junit 测试并在运行时导致 Android不一样。

private const val REGEX = "GE[a-zA-Z0-9]{2}\s?([a-zA-Z0-9]{2})([0-9]{2}\s?)([0-9]{4}\s?){3}([0-9]{2})\s?"
private val PATTERN: Pattern = Pattern.compile(REGEX, Pattern.MULTILINE or Pattern.CASE_INSENSITIVE)

fun find(text: String): List<String> {
    val textFormatted = text.replace("\s".toRegex(), "")
    val list = ArrayList<String>()
    val matcher = matcher(textFormatted)
    when {
        matcher.matches() -> {
            list.add(textFormatted)
        }
        matcher.find() -> {
            val partitions = findGroupMatches(matcher)
            list.addAll(partitions)
        }
    }
    return list
}

private fun findGroupMatches(matcher: Matcher): List<String> {
    val partitions = mutableListOf<String>()
    for (i in 0 until matcher.groupCount()) {
        val partition = matcher.group(i)
        if (partition != null && PATTERN.matcher(partition).matches()) {
            partitions.add(partition.replace("\s".toRegex(), ""))
        }
    }
    return partitions
}

魔术(恕我直言)就发生在这里

On JVM tests, it returns emptyList

@Test
fun `find with not valid text returns emptyList`(){
    val targets = PatternUtils.find("GE03TB 7433311450666666300008")
    assertTrue(targets.isEmpty()) // success
}

PatternUtils.find("GE03TB 7433311450666666300008") on Android inside `onCreate()` returns 1 size list("GE03TB743331145066666") //

为什么会这样?有什么错误吗?还是我遗漏了什么?

原因是 Oracle 和 Google 的 Pattern.java 实现不同。

为了类似地工作,我不得不创建新的 Matcher 而不是重复使用它。 (Matcher.java有些方法有副作用)

fun find(text: String): List<String> {
    val textFormatted = text.replace("\s".toRegex(), "")
    val list = ArrayList<String>()
    val matcher = createMatcher(textFormatted)
    when {
        createMatcher(textFormatted).matches() -> {
            list.add(textFormatted)
        }
        matcher.find() -> {
            val partitions = findGroupMatches(matcher)
            list.addAll(partitions)
        }
    }
    return list
}