如何对使用上下文的 class 进行单元测试?

How to unit test a class that uses context?

我正在尝试测试一个简单的方法。

我有这个class:

class Cloud @Inject constructor(var posx: Double = 0.0, var posy: Double = 0.0, var velocity: 
    Double = 1.0, val context: Context){

    val image: Bitmap = BitmapFactory.decodeResource(context.resources, R.raw.cloud)

    fun updateVelocity(){
        velocity += 5.0
    }

    fun draw(canvas: Canvas){
        canvas.drawBitmap(image,posx.toFloat() - (image.width / 2),posy.toFloat(),null)
    }    
}

我想对 updateVelocity() 方法进行单元测试,但我不知道该怎么做,我应该使用仪器测试并通过上下文还是可以使用类似 mockk 的东西?

我可以用 mockk 做这个吗?

@Test
fun cloudVelocity() { 
    val cloud: Cloud = mockk()                
    //update cloud velocity
    //assert that the velocity changed 
}

在这种情况下很难对您的 class 进行单元测试,因为它不仅取决于上下文,还取决于 BitmapBitmapFactoryCanvas

如果您在不同的 classes 中分离业务和绘图逻辑,也许会更好。例如,您的 Cloud 对象将仅包含纯业务逻辑,您可以轻松地对其进行测试。另一方面,您可以创建 CloudDrawer class,其中将包含 Canvas/Context/Bitmap

的绘图逻辑

在大多数更简单的情况下,您可以使用特殊界面替换 Context。例如,我们在 classes 中使用 getString()。但是我们想测试这些 classes。在这种情况下,我们在 Context:

上使用这种抽象
interface ResourceManager {
    fun getColor(@ColorRes resId: Int): Int
    fun getDrawable(@DrawableRes resId: Int): Drawable?
    fun getString(@StringRes resId: Int): String
    fun getString(@StringRes resId: Int, vararg formatArgs: Any): String
    fun getStringArray(@ArrayRes resId: Int): Array<String>
    fun getQuantityString(@PluralsRes resId: Int, quantity: Int, formatArgs: Int): String
}

模拟这个接口很容易:

 val resource = mock(ResourceManager::class.java)
 `when`(resource.getString(any(Int::class.java))).thenReturn("text")