I want to test the result of a function of a class. And it returns an instance of an Android class, which should be mocked in a unit test since it seems to be stubbed in any unit test.
Here's a minimized example code of the simulated android class, AndroidData
, and the class to be tested, MyHelper
.
/**
* Should be mocked in a unit test.
*/
class AndroidData(val value: Float)
/**
* Target class to be tested.
*/
class MyHelper() {
fun createData(flag: Boolean): AndroidData {
// simplified logic
return if (flag) AndroidData(20f) else AndroidData(10f)
}
}
What I want to achieve is something like this( note that this is incorrect code ):
class MyHelperTest : TestCase() {
@Test
fun testCreateData() {
mockkConstructor(AndroidData::class)
val valueSlot = slot<Float>()
every { constructedWith<AndroidData>(capture(valueSlot)) } // Type mismatch in IDE
val helper = MyHelper()
val returnedData = helper.createData(true)
assertTrue(returnedData.value >= 15f)
}
}
I want to test that returned AndroidData
instance has a correct value
, or matches some conditions. I cannot find any tutorial about this case or any correct way to implement it.
These 2 test cases would both fail.
@Test
fun testCreateData1() {
mockkConstructor(AndroidData::class)
val helper = mockk<MyHelper>(relaxed = true)
val createdData = helper.createData(true)
println("createdData=$createdData") // AndroidData(child of #1#2)
println("createdData.value=${createdData.value}") // 0.0
// test if the argument in AndroidData's constructor was larger than 15
assertTrue(createdData.value >= 15f) // assertion failed
}
@Test
fun testCreateData2() {
mockkConstructor(AndroidData::class)
// raise error: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
every {
constructedWith<AndroidData>(LargerThan15Matcher())
}
val helper = mockk<MyHelper>(relaxed = true)
val createdData = helper.createData(true)
println("createdData=$createdData") // AndroidData(child of #1#2)
println("createdData.value=${createdData.value}") // 0.0
// test if the argument in AndroidData's constructor was larger than 15
assertTrue(createdData.value >= 15f)
}
The testing idea was pretty easy and intuitive for Python unittest in my experience. Yet it seems impossible in Java or Android? I haven't tried the mockito
and roboletric
library because I was told that mockk
provides support on Android projects. Or I just haven't found the correct way to do this, or the whole testing idea is completely wrong? Please end my days of searching and struggle.
It is not really clear to me what you are trying to achieve, but I can try to help you with what I think I understand.
Let's start with your test-case testCreateData1
:
MyHelper
returns AndroidData(0.0)
which does not satisfy your assertion. Regarding test-case testCreateData2
:
every {... }
alone is not a proper expression, but it is intended to specify what should happen on every ...
. For instance, if you have a mock m
with a function f
you could write something like the following:every { m.f() } returns 42
every { m.f() } answers { callOriginal() }
constructedWith<AndroidData>(LargerThan15Matcher())
is not a proper expression, because it is intended to specify what should happen with an AndroidData constructed with an argument matched by the LargerThan15Matcher
. For instance, if you want to say that the value
of such an object should always return 1 you could write every { constructedWith<AndroidData>(LargerThan15Matcher()).value } returns 1f
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.