50

I'm stuck trying to mock some stuff with mockk:

I have the following setup on gradle

root:
  |-- App (just a sample app for the SDK)
  |-- SDK (SDK we develop) << apply plugin: 'com.android.library'
       |-- SDKimpl.kt
  |-- Foo (wrapper around a .jar library) << apply plugin: 'com.android.library'
       |-- Foo.kt

So I'm writing an androidTest for the SDK and trying to mock Foo.kt. There's nothing unusual about Foo class, just direct class Foo(private val someParams) {

So using androidTestImplementation "io.mockk:mockk-android:1.8.13" the mock goes:

val mock: Foo = mockk()
// val mock: Foo = mockkClass(Foo::class) // also tried this
every { mock.getData() } returns listOf("1", "2", "3")

I'm always getting the following crash:

io.mockk.MockKException: Missing calls inside every { ... } block.
at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:42)

Also tried just to gather information:

  • running inside JVM test folder. It gets mocked without issues, but I can't run my test as JVM
  • running androidTest inside Foo module. Got the same crash
  • using mockkClass(Foo::class). Got some crash
  • using annotation @MockK and MockKAnnotations.init(this). Got some crash.
  • added Log.d before every { line and inside getData() method and it seems the actual real method from the class is getting called during the mock setup. That seems super weird to me.

Any idea what's going wrong here?

edit:

as requested, full code. I'm current working on an isolated project to try to isolate the error, so Foo is just:

class Foo {

    fun getData(): String {
        Log.d(TAG, "invoked foo.getData()")
        return "trolololo"
    }

}

and then I have FooTest in androidTest:

class FooTest {

    @Test
    fun mock_foo() {
        val foo = mockk<Foo>()
        every { foo.getData() } returns "zero"
        assertEquals("zero", foo.getData())
    }

}
Budius
  • 39,391
  • 16
  • 102
  • 144

9 Answers9

21

It seems to be a Mockk opened issue: https://github.com/mockk/mockk/issues/182

2 possible quick fixes (pick one):

  1. Run the Instrumented Tests in an emulator >= Android-P
  2. Set Foo class as open (and the method(s) you want to mock too)
Phil
  • 4,730
  • 1
  • 41
  • 39
20

Try to check the official guide and see what is missing.

In my case, I tried to mock an extension in Kotlin but missed the mockkStatic

fun Date.asMyTime() : DateTime = DateTime(this, DateTimeZone.getDefault())

mockkStatic("packageName.FileNameKt") // This is what I was missing
every {
    DateTime().asMyTime()
} returns mock(DateTime::class.java)
Allen
  • 2,979
  • 1
  • 29
  • 34
  • Thanks for `mockkStatic("packageName.FileNameKt")` when test extension method! Did you mean `mockk`, not `mock` in the last line? – CoolMind Mar 31 '22 at 23:04
  • 1
    Instead of `mockkStatic("packageName.FileNameKt")` you can write: `mockkStatic(FileName::class.java.name + "Kt")`. – CoolMind Apr 01 '22 at 14:40
16

In my case I forgot to spyk the class I was applying every {...} to.

val presenter = spyk(MyPresenter())

every { view.myFun(any()) } returns Unit
Tom
  • 6,946
  • 2
  • 47
  • 63
  • Can we add `any()` to `spyk` – Akshay Hazari Dec 23 '21 at 07:13
  • 4
    @AkshayHazari `spyk` is used to add mocking and verification abilities to "real" objects. Anything that can be done with `mockk`s can be done on `spyk`'d objects, such as `every{}`, `verify{}` etc. – Tom Dec 28 '21 at 22:33
7

In my case, I've missed

@Before
fun setUp() {
    MockKAnnotations.init(this)
}
Aneczka
  • 79
  • 1
  • 1
7

In my case I tried to mock using mock() function instead mockk() (double k)

Sergey Bulavkin
  • 2,325
  • 2
  • 17
  • 26
4

Make sure the object is really a mock, not the real object.

For instance:

- Sdk sdk = Sdk()
+ Sdk sdk = mockk()
  every { sdk.crypto } returns mockk()
tonisives
  • 1,962
  • 1
  • 18
  • 17
4

My problem was that I used a java class without getters

public class KeyStorePasswordPair {
    public KeyStore keyStore;
    public String keyPassword;

    public KeyStorePasswordPair(KeyStore keyStore, String keyPassword) {
        this.keyStore = keyStore;
        this.keyPassword = keyPassword;
    }
}

I needed to add getters for the variables to make mockking work:

public class KeyStorePasswordPair {
    public KeyStore getKeyStore() {
        return keyStore;
    }

    public String getKeyPassword() {
        return keyPassword;
    }

    private KeyStore keyStore;
    private String keyPassword;

    public KeyStorePasswordPair(KeyStore keyStore, String keyPassword) {
        this.keyStore = keyStore;
        this.keyPassword = keyPassword;
    }
}

tonisives
  • 1,962
  • 1
  • 18
  • 17
2

Mockk Missing calls inside every { ... } block

may also be thrown when you have an every block defined on an object that is not a mockk, for example:

You define stub behavior like this

every { foo.getData() } returns DATA

and then try to:

every { DATA.getVersion() } returns VERSION

Where DATA and VERSION objects are declared (and instantiated) in the test class.

The error message is not very informative and a bit misleading in that case.

Balu
  • 522
  • 6
  • 16
-5

try like this

`when`(mock.getData()).thenReturn(listOf("1", "2", "3"))
Ankitech
  • 9
  • 1
  • 3