9

I'm trying to mock an Android Context to return a string from a resource id. However I have trouble matching the stub to the call, I assume it is because of the varargs. However I am new to mockk so I might just miss something very easy.

I mock the context this way:

val context = mockk<Context>()
every { context.getString(any(), any()) } returns stringToReturn

But when calling getString on the object it throws the following exception:

io.mockk.MockKException: no answer found for: Context(#1).getString(2131689544, [])

If it is important, I call the function in the class under test similar to this. formatArgs may be empty but doesn't have to:

protected fun foo(stringResource: Int, vararg formatArgs: Any) {
    val s = context.getString(errorMessageStringResource, *formatArgs)

Any idea how I can fix this?

You can check the project and reproduce the exception here: Github Project

findusl
  • 2,454
  • 8
  • 32
  • 51
  • I didnt down vote, but think that such things should be reported as issues only. Questions on SO is more for something missing in docs e.t.c. – oleksiyp Jan 24 '19 at 15:21
  • 1
    @oleksiyp The docs for mockk do not describe how to handle varargs so it is missing in the docs. When asking the question it was not clear to me that this is an issue with the library and I am still not certain that there is no better workaround than fallback to a different mocking framework. Maybe someone still has an idea that I can't think of. – findusl Jan 24 '19 at 15:25

2 Answers2

7

Version 1.9.1 introduces few additional matchers to match varargs.

https://mockk.io/#varargs

oleksiyp
  • 2,659
  • 19
  • 15
1

There is a related open issue in mockk v1.9: https://github.com/mockk/mockk/issues/224 (see referenced issues as well)

I tried several solutions but I ended up creating overloaded functions just for testing with mockk, eg.

class Context {
    // Renamed because of same JVM signature
    fun foo2(stringResource: Int, vararg formatArgs: Any) = foo(stringResource, formatArgs)

    // Function accepts 
    fun foo(stringResource: Int, formatArgs: args: Array<out Any>) = ...
}

then test the non-vararg foo() function with mockk.

I know it's an ugly workaround but if you find a better one please let me know :)

snorbi
  • 2,590
  • 26
  • 36
  • 1
    Thanks for the issue reference, upvote for that. I can't really do the solution because the function that I am trying to stub is not mine, but from context. I think I might have to mock it with Mockito or something else in java and pass it to the Kotlin code. – findusl Jan 24 '19 at 13:32
  • 1
    Hopefully there will be some time to do this changes. I have another guy who wants to help me on coding, but first we need to design it together. Both ways I cant promise it will be fast – oleksiyp Jan 24 '19 at 15:19