mockito-kotlin icon indicating copy to clipboard operation
mockito-kotlin copied to clipboard

Invocation count is wrong when capturing arguments against sealed class types

Open gosr opened this issue 6 years ago • 1 comments
trafficstars

Assume you have a sealed class hierarchy as follows:

sealed class MyType {
  data class Open(val something: String) : MyType()
  data class Finish(val reason: String) : MyType()
}

Let's say the production code that I'm verifying against has a method with the following structure:

class MyClass {
  fun doStuff(myType: MyType) {
    // ...
  }
}

So, somewhere in the production code we do this: myClass.doStuff(MyType.Open("something")). Later, in another place, we do this: myClass.doStuff(MyType.Finish("reason")).

In my test, this is the setup I am trying to use for verifying that myClass invoked doStuff() exactly once with the parameter MyType.Finish:

import com.nhaarman.mockitokotlin2.argumentCaptor
import org.mockito.Mockito.*

@Test
fun someTest() {
  argumentCaptor<MyType.Finish>().apply {
    verify(myClass, times(1)).send(capture())
  }
}

The test fails with the following output:

org.mockito.exceptions.verification.TooManyActualInvocations: myClass.doStuff(<Capturing argument>); Wanted 1 time: -> at "location in test method" But was 2 times: -> at "location where I call myClass.doStuff(MyType.Open("something"))" -> at "location where I call myClass.doStuff(MyType.Finish("reason"))"

So, the argumentCaptor specified with the type MyType.Finish captures all invocations where the superclass MyType is used.

gosr avatar Jun 27 '19 09:06 gosr

This seems to be related: https://stackoverflow.com/questions/5403706/using-mockitos-argumentcaptor-class-to-match-a-child-class

nhaarman avatar Jul 05 '19 14:07 nhaarman