【问题标题】:Android use android.graphics.Matrix in Unit TestAndroid 在单元测试中使用 android.graphics.Matrix
【发布时间】:2023-04-02 14:00:01
【问题描述】:

有没有办法在 Android 的本地单元测试中使用 android.graphics.Matrix。当我尝试使用矩阵对象时,我收到错误消息:java.lang.RuntimeException: Method getValues in android.graphics.Matrix not mocked.

我怀疑由于 Matrix 类使用本机方法,这意味着该类不能用于本地单元测试。所以为了使用它,我必须使用例如 Mockito 创建一个模拟对象。这是一个创建模拟对象的示例,它总是返回单位矩阵。

    /**
     * Create Mockito graphic matrix, since the matrix methods are native and are not supported
     * in local unit testing. We need to use Mockito to mock a matrix, that always return the
     * identity matrix, when getValues() method is called. Identity matrix is the default matrix 
     * with no transformations applied to it.
     */
    fun getMockMatrix(): Matrix {

        val mockMatrix = mock(Matrix::class.java)
        doAnswer { invocation ->

            val v = (invocation.arguments[0] as FloatArray)

            // always set values to match the identity matrix, when getValues() method is called
            v[0] = 1f
            v[4] = 1f
            v[8] = 1f

            null
        }.`when`(mockMatrix).getValues(FloatArray(9))

        val matrixValues = FloatArray(9)
        mockMatrix.getValues(matrixValues)

        // check if the mocked matrix matches the identity matrix
        assertArrayEquals(
            matrixValues, floatArrayOf(
                1f, 0f, 0f,
                0f, 1f, 0f,
                0f, 0f, 1f
            )
        )
        return mockMatrix
    }

这在某些情况下效果很好,例如当我需要将其用作虚拟对象时,但当我需要对其或映射点进行实际转换时,无法使用模拟对象来实现它。

现在我使用Instrumented Test 进行了测试,因为它使用模拟器,这样它就可以访问集成在 Android 操作系统中的本地方法,但是这些类型的测试比本地单元测试要慢得多。我的问题是,是否有办法创建可以使用 Matrix 类的本地单元测试?

【问题讨论】:

    标签: android unit-testing kotlin matrix


    【解决方案1】:
    1. 使用Robolectric。它将提供可以在本地 JVM 上运行的 Matrix 实现,因此您不必使用自己的模拟。使用 Robolectric 的缺点是您正在测试 Robolectric 的 Android SDK 实现,这可能与在实际设备上运行的实际代码一致,也可能不一致。也就是说,Robolectric 已经存在了一段时间,并且由 Google 维护,所以应该可以安全使用。

    2. 从您的代码中抽象出Matrix。模拟您不拥有的类型通常不是一个好习惯,因为当您针对实际实现运行时,您不可避免地会对该类型的实现做出假设,这些假设可能会或可能不会成立。为您自己的类型创建测试替身是安全的,因为您可以控制行为。在Matrix 上创建一个薄包装器,您可以在测试中模拟/伪造它本身不需要单元测试是我建议的解决方案。

    【讨论】:

      【解决方案2】:

      我认为这与框架类中的本地方法使用没有任何关系。当您使用任何 Android 框架类时,也会发生同样的情况。例如,我对android.graphics.Point 有同样的问题。这是一个非常基本的类,只包含一个 x 和一个 y 坐标,但不能用于单元测试。

      在这种情况下,我们可以做的是创建我们自己的该类版本,该版本仅用于单元测试。因此,在您的测试目录树下,只需创建类 android.graphics.Matrix(具有完全相同的完全限定类名)并创建一个虚拟实现(或者只是从 the Android source code 复制它 - 虽然不确定它将如何与本机代码一起使用)。然后,当单元测试运行时,您的单元测试代码和实际的主分支代码都将使用该版本的类。但由于它只存在于测试目录树中,因此在您的实际应用运行时不会使用它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-22
        相关资源
        最近更新 更多