[英]mock nested properties in mockk
I have a function which uses a field in DisplayMetrics
of Resources
of Context
class:我有一个 function,它使用
DisplayMetrics
of Resources
of Context
class 中的一个字段:
fun getIconForDevice(context: Context, iconUrl: String): String {
val metrics = context.resources.displayMetrics
var suffix = ""
//below checks MUST be in this increasing order or it may failed
if (metrics.densityDpi <= DisplayMetrics.DENSITY_MEDIUM)
suffix = "-m"
else if (metrics.densityDpi <= DisplayMetrics.DENSITY_HIGH)
suffix = "-h"
else if (metrics.densityDpi <= DisplayMetrics.DENSITY_XHIGH)
suffix = "-xh"
else if (metrics.densityDpi <= DisplayMetrics.DENSITY_XXHIGH || metrics.densityDpi > DisplayMetrics.DENSITY_XXHIGH)
suffix = "-xxh"
val pasvand = iconUrl.substring(iconUrl.lastIndexOf("."))
val str = iconUrl.substring(0, iconUrl.lastIndexOf(".")) + suffix + pasvand
return str
}
In order to test it, I need to mock Context
and metrics.densityDpi
to give it a value.为了测试它,我需要模拟
Context
和metrics.densityDpi
来给它一个值。
I'm using Mockk (1.9.3) library to do that.我正在使用Mockk (1.9.3)库来做到这一点。
@Test
fun getIconForDevice_ReturnsUrlWithXxhForXxhDisplay() {
val context: Context = mockk(relaxed = true)
every { context.resources.displayMetrics.densityDpi } returns 450
assertEquals(IconHelper.getIconForDevice(context,
"https://website.com/image.png"), "https://website.com/image-xxh.png")
}
Running the test following error stacktrace is given:给出以下错误堆栈跟踪运行测试:
java.lang.ClassCastException: java.lang.Integer cannot be cast to android.util.DisplayMetrics
at ...Resources.getDisplayMetrics(Resources.java)
at ....IconHelper.getIconForDevice(IconHelper.kt:39)
at ...IconHelperTest.getIconForDevice_ReturnsUrlWithXxhForXxhDisplay(IconHelperTest.kt:30)
The first link refers to val metrics = context.resources.displayMetrics
line of the actual function第一个链接是指实际 function 的
val metrics = context.resources.displayMetrics
行
So how can I mock such a nested field in mockk?那么如何在 mockk 中模拟这样一个嵌套字段呢?
context.resources.displayMetrics.densityDpi
Your setup of mocking Context
and densityDpi
is correct.您对 mocking
Context
和densityDpi
的设置是正确的。
The test fails because you are calling getIconForDevice
with a new mockk instead of your mocked Context
.测试失败,因为您使用新的模拟调用
getIconForDevice
而不是模拟的Context
。
@Test
fun getIconForDevice_ReturnsUrlWithXxhForXxhDisplay() {
val context: Context = mockk(relaxed = true)
every { context.resources.displayMetrics.densityDpi } returns 450
// pass in mocked context
assertEquals(IconHelper.getIconForDevice(context, "https://website.com/image.png"), "https://website.com/image-xxh.png")
}
Regarding your ClassCastException
, because you are accessing the DisplayMetrics
first:关于您的
ClassCastException
,因为您首先访问DisplayMetrics
:
val metrics = context.resources.displayMetrics
I think you need to separate the mock of displayMetrics
and densityDpi
:我认为您需要将
displayMetrics
和densityDpi
的模拟分开:
@Test
fun getIconForDevice_ReturnsUrlWithXxhForXxhDisplay() {
val context: Context = mockk(relaxed = true)
val displayMetrics: DisplayMetrics = mockk(relaxed = true) // maybe relaxed is not needed, I just put it here in case
every { context.resources.displayMetrics } returns displayMetrics
every { displayMetrics.densityDpi } returns 450
assertEquals(IconHelper.getIconForDevice(context, "https://website.com/image.png"), "https://website.com/image-xxh.png")
}
In version 1.12.0 Run as unit test kotlin 1.5.10在 1.12.0 版本中作为单元测试运行 kotlin 1.5.10
// WORKS
val context: Context = mockk()
every { context.resources.displayMetrics } returns DisplayMetrics().apply {
this.densityDpi = DisplayMetrics.DENSITY_LOW
}
ERROR - returns class java.lang.Integer cannot be cast to class android.util.DisplayMetrics ERROR - returns class java.lang.Integer cannot be cast to class android.util.DisplayMetrics
val context: Context = mockk()
every { context.resources.displayMetrics.densityDpi } returns DisplayMetrics.DENSITY_LOW
ERROR - returns Missing mocked calls inside every {... } block: make sure the object inside the block is a mock错误 - 在每个 {... } 块内返回缺失的模拟调用:确保块内的 object 是模拟的
val context: Context = mockk()
val displayMetrics: DisplayMetrics = mockk()
every { context.resources.displayMetrics } returns displayMetrics
every { displayMetrics.densityDpi } returns DisplayMetrics.DENSITY_LOW
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.