Git Product home page Git Product logo

mockk's Introduction

drawing drawing

Relase Version Change log codecov Android Matrix tests Open Source Helpers

Getting started

All you need to get started is just to add a dependency to MockK library.

Gradle/Maven dependency

ApproachInstruction
Gradle
testImplementation "io.mockk:mockk:${mockkVersion}"
Gradle (Kotlin DSL)
testImplementation("io.mockk:mockk:${mockkVersion}")
Maven
 <dependency>
     <groupId>io.mockk</groupId>
     <artifactId>mockk-jvm</artifactId>
     <version>${mockkVersion}</version>
     <scope>test</scope>
 </dependency>
android Unit
testImplementation "io.mockk:mockk-android:${mockkVersion}"
testImplementation "io.mockk:mockk-agent:${mockkVersion}"
android Instrumented
androidTestImplementation "io.mockk:mockk-android:${mockkVersion}"
androidTestImplementation "io.mockk:mockk-agent:${mockkVersion}"

DSL examples

Simplest example. By default mocks are strict, so you need to provide some behaviour.

val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

verify { car.drive(Direction.NORTH) }

confirmVerified(car)

See the "Features" section below for more detailed examples.

Spring support

Quarkus support

  • quarkus-mockk adds support for mocking beans in Quarkus. Documentation can be found here

Kotlin version support

From version 1.13.0 MockK supports Kotlin 1.4 and higher

Known issues

  • PowerMock needs a workaround to run together with MockK #79. (not sure after workaround if it is generally usable or not, please somebody report it)
  • Inline functions cannot be mocked: see the discussion on this issue
  • Spies, mockkStatic may not work on JDK 16+; InaccessibleObjectException/IllegalAccessException: read more here
  • Using a spy with a suspending function will give unexpected test results

Table of contents:

  • auto-gen TOC: {:toc}

Examples, guides & articles

Kotlin Academy articles

Check the series of articles "Mocking is not rocket science" at Kt. Academy describing MockK from the very basics of mocking up to description of all advanced features.

Japanese guides and articles

Chinese guides and articles

Korean guides and articles

Features

Annotations

You can use annotations to simplify the creation of mock objects:

class TrafficSystem {
  lateinit var car1: Car
  
  lateinit var car2: Car
  
  lateinit var car3: Car
}

class CarTest {
  @MockK
  lateinit var car1: Car

  @RelaxedMockK
  lateinit var car2: Car

  @MockK(relaxUnitFun = true)
  lateinit var car3: Car

  @SpyK
  var car4 = Car()
  
  @InjectMockKs
  var trafficSystem = TrafficSystem()
  
  @Before
  fun setUp() = MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for all mocks

  @Test
  fun calculateAddsValues1() {
      // ... use car1, car2, car3 and car4
  }
}

Injection first tries to match properties by name, then by class or superclass. Check the lookupType parameter for customization.

Properties are injected even if private is applied. Constructors for injection are selected from the biggest number of arguments to lowest.

@InjectMockKs by default injects only lateinit vars or vars that are not assigned. To change this, use overrideValues = true. This would assign the value even if it is already initialized somehow. To inject vals, use injectImmutable = true. For a shorter notation use @OverrideMockKs which does the same as @InjectMockKs by default, but turns these two flags on.

JUnit4

JUnit 4 exposes a rule-based API to allow for some automation following the test lifecycle. MockK includes a rule which uses this to set up and tear down your mocks without needing to manually call MockKAnnotations.init(this). Example:

class CarTest {
  @get:Rule
  val mockkRule = MockKRule(this)

  @MockK
  lateinit var car1: Car

  @RelaxedMockK
  lateinit var car2: Car

  @Test
  fun something() {
     every { car1.drive() } just runs
     every { car2.changeGear(any()) } returns true
     // etc
  }
}

JUnit5

In JUnit5 you can use MockKExtension to initialize your mocks.

@ExtendWith(MockKExtension::class)
class CarTest {
  @MockK
  lateinit var car1: Car

  @RelaxedMockK
  lateinit var car2: Car

  @MockK(relaxUnitFun = true)
  lateinit var car3: Car

  @SpyK
  var car4 = Car()

  @Test
  fun calculateAddsValues1() {
      // ... use car1, car2, car3 and car4
  }
}

Additionally, it adds the possibility to use @MockK and @RelaxedMockK on test function parameters:

@Test
fun calculateAddsValues1(@MockK car1: Car, @RelaxedMockK car2: Car) {
  // ... use car1 and car2
}

Finally, this extension will call unmockkAll and clearAllMocks in a @AfterAll callback, ensuring your test environment is clean after each test class execution. You can disable this behavior by adding the @MockKExtension.KeepMocks annotation to your class or globally by setting the mockk.junit.extension.keepmocks=true property. (Since v1.13.11) Alternatively, since clearAllMocks is not thread-safe, if you need to run test in parallel you can add the MockKExtension.RequireParallelTesting annotation to your class or set the mockk.junit.extension.requireParallelTesting=true property to disable calling it in the @AfterAll callback.

Automatic verification confirmation

You can make sure that all stubbed methods are actually verified by also annotating your test class with @MockKExtension.ConfirmVerification.

This will internally call confirmVerified on all mocks after each test, to make sure there are no unnecessary stubbings.

Please note that this behavior may not work as expected when running tests in your IDE, as it is Gradle who takes care of handling the exception being thrown when these confirmVerified calls fail.

Automatic unnecessary stubbing check

You can make sure that all stubbed methods are useful - used at least once - by also annotating your test class with @MockKExtension.CheckUnnecessaryStub.

This will internally call checkUnnecessaryStub on all mocks after each test, to make sure there are no unnecessary stubbings.

Spy

Spies allow you to mix mocks and real objects.

val car = spyk(Car()) // or spyk<Car>() to call the default constructor

car.drive(Direction.NORTH) // returns whatever the real function of Car returns

verify { car.drive(Direction.NORTH) }

confirmVerified(car)

Note 1: the spy object is a copy of the passed object. Note 2: there is a known issue if using a spy with a suspending function: #554

Relaxed mock

A relaxed mock is the mock that returns some simple value for all functions. This allows you to skip specifying behavior for each case, while still stubbing things you need. For reference types, chained mocks are returned.

val car = mockk<Car>(relaxed = true)

car.drive(Direction.NORTH) // returns null

verify { car.drive(Direction.NORTH) }

confirmVerified(car)

Note: relaxed mocking is working badly with generic return types. A class cast exception is usually thrown in this case. Opt for stubbing manually in the case of a generic return type.

Workaround:

val func = mockk<() -> Car>(relaxed = true) // in this case invoke function has generic return type

// this line is workaround, without it the relaxed mock would throw a class cast exception on the next line
every { func() } returns Car() // or you can return mockk() for example 

func()

Partial mocking

Sometimes, you need to stub some functions, but still call the real method on others, or on specific arguments. This is possible by passing callOriginal() to answers, which works for both relaxed and non-relaxed mocks.

class Adder {
 fun addOne(num: Int) = num + 1
}

val adder = mockk<Adder>()

every { adder.addOne(any()) } returns -1
every { adder.addOne(3) } answers { callOriginal() }

assertEquals(-1, adder.addOne(2))
assertEquals(4, adder.addOne(3)) // original function is called

Mock relaxed for functions returning Unit

If you want Unit-returning functions to be relaxed, you can use relaxUnitFun = true as an argument to the mockk function, @MockKannotation or MockKAnnotations.init function.

Function:

mockk<ClassBeingMocked>(relaxUnitFun = true)

Annotation:

@MockK(relaxUnitFun = true)
lateinit var mock1: ClassBeingMocked
init {
    MockKAnnotations.init(this)
}

MockKAnnotations.init:

@MockK
lateinit var mock2: ClassBeingMocked
init {
    MockKAnnotations.init(this, relaxUnitFun = true)
}

Object mocks

Objects can be turned into mocks in the following way:

object ObjBeingMocked {
  fun add(a: Int, b: Int) = a + b
}

mockkObject(ObjBeingMocked) // applies mocking to an Object

assertEquals(3, ObjBeingMocked.add(1, 2))

every { ObjBeingMocked.add(1, 2) } returns 55

assertEquals(55, ObjBeingMocked.add(1, 2))

To revert back, use unmockkObject or unmockkAll (more destructive: cancels object, static and constructor mocks)

@Before
fun beforeTests() {
    mockkObject(ObjBeingMocked)
    every { ObjBeingMocked.add(1,2) } returns 55
}

@Test
fun willUseMockBehaviour() {
    assertEquals(55, ObjBeingMocked.add(1,2))
}

@After
fun afterTests() {
    unmockkObject(ObjBeingMocked)
    // or unmockkAll()
}

Despite the Kotlin language restrictions, you can create new instances of objects if required by testing logic:

val newObjectMock = mockk<ObjBeingMocked>()

Class mock

Sometimes you need a mock of an arbitrary class. Use mockkClass in those cases.

val car = mockkClass(Car::class)

every { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

verify { car.drive(Direction.NORTH) }

Enumeration mocks

Enums can be mocked using mockkObject:

enum class Enumeration(val goodInt: Int) {
    CONSTANT(35),
    OTHER_CONSTANT(45);
}

mockkObject(Enumeration.CONSTANT)
every { Enumeration.CONSTANT.goodInt } returns 42
assertEquals(42, Enumeration.CONSTANT.goodInt)

Constructor mocks

Sometimes, especially in code you don't own, you need to mock newly created objects. For this purpose, the following constructs are provided:

class MockCls {
  fun add(a: Int, b: Int) = a + b
}

mockkConstructor(MockCls::class)

every { anyConstructed<MockCls>().add(1, 2) } returns 4

assertEquals(4, MockCls().add(1, 2)) // note new object is created

verify { anyConstructed<MockCls>().add(1, 2) }

The basic idea is that just after the constructor of the mocked class is executed (any of them), objects become a constructed mock.
Mocking behavior of such a mock is connected to the special prototype mock denoted by anyConstructed<MockCls>().
There is one instance per class of such a prototype mock. Call recording also happens to the prototype mock.
If no behavior for the function is specified, then the original function is executed.

In case a class has more than one constructor, each can be mocked separately:

class MockCls(private val a: Int = 0) {
  constructor(x: String) : this(x.toInt())  
  fun add(b: Int) = a + b
}

mockkConstructor(MockCls::class)

every { constructedWith<MockCls>().add(1) } returns 2
every { 
    constructedWith<MockCls>(OfTypeMatcher<String>(String::class)).add(2) // Mocks the constructor which takes a String
} returns 3
every {
    constructedWith<MockCls>(EqMatcher(4)).add(any()) // Mocks the constructor which takes an Int
} returns 4

assertEquals(2, MockCls().add(1))
assertEquals(3, MockCls("2").add(2))
assertEquals(4, MockCls(4).add(7))

verify { 
    constructedWith<MockCls>().add(1)
    constructedWith<MockCls>("2").add(2)
    constructedWith<MockCls>(EqMatcher(4)).add(7)
}

Note that in this case, a prototype mock is created for every set of argument matchers passed to constructedWith.

Partial argument matching

You can mix both regular arguments and matchers:

val car = mockk<Car>()

every { 
  car.recordTelemetry(
    speed = more(50),
    direction = Direction.NORTH, // here eq() is used
    lat = any(),
    long = any()
  )
} returns Outcome.RECORDED

car.recordTelemetry(60, Direction.NORTH, 51.1377382, 17.0257142)

verify { car.recordTelemetry(60, Direction.NORTH, 51.1377382, 17.0257142) }

confirmVerified(car)

Chained calls

You can stub chains of calls:

val car = mockk<Car>()

every { car.door(DoorType.FRONT_LEFT).windowState() } returns WindowState.UP

car.door(DoorType.FRONT_LEFT) // returns chained mock for Door
car.door(DoorType.FRONT_LEFT).windowState() // returns WindowState.UP

verify { car.door(DoorType.FRONT_LEFT).windowState() }

confirmVerified(car)

Note: if the function's return type is generic then the information about the actual type is gone.
To make chained calls work, additional information is required.
Most of the time the framework will catch the cast exception and do autohinting.
In the case it is explicitly required, use hint before making the next call.

every { obj.op2(1, 2).hint(Int::class).op1(3, 4) } returns 5

Hierarchical mocking

From version 1.9.1 mocks may be chained into hierarchies:

interface AddressBook {
    val contacts: List<Contact>
}

interface Contact {
    val name: String
    val telephone: String
    val address: Address
}

interface Address {
    val city: String
    val zip: String
}

val addressBook = mockk<AddressBook> {
    every { contacts } returns listOf(
        mockk {
            every { name } returns "John"
            every { telephone } returns "123-456-789"
            every { address.city } returns "New-York"
            every { address.zip } returns "123-45"
        },
        mockk {
            every { name } returns "Alex"
            every { telephone } returns "789-456-123"
            every { address } returns mockk {
                every { city } returns "Wroclaw"
                every { zip } returns "543-21"
            }
        }
    )
}

Capturing

You can capture an argument to a CapturingSlot or MutableList.

CapturingSlot is usually created via factory method slot<T : Any?>() and is possible to capture nullable and non nullable types. MutableList is intended for capturing multiple values during testing.

enum class Direction { NORTH, SOUTH }
enum class RecordingOutcome { RECORDED }
enum class RoadType { HIGHWAY }
class Car {
    fun recordTelemetry(speed: Double, direction: Direction, roadType: RoadType?): RecordingOutcome {
        TODO("not implement for showcase")
    }
}

val car = mockk<Car>()
// allow to capture parameter with non nullable type `Double`
val speedSlot = slot<Double>()
// allow to capture parameter with nullable type `RoadType`
val roadTypeSlot = slot<RoadType?>()
val list = mutableListOf<Double>()

every {
    car.recordTelemetry(
        speed = capture(speedSlot), // makes mock match calls with any value for `speed` and record it in a slot
        direction = Direction.NORTH, // makes mock and capturing only match calls with specific `direction`. Use `any()` to match calls with any `direction`
        roadType = captureNullable(roadTypeSlot), // makes mock match calls with any value for `roadType` and record it in a slot
    )
} answers {
    println("Speed: ${speedSlot.captured}, roadType: ${roadTypeSlot.captured}")

    RecordingOutcome.RECORDED
}

every {
    car.recordTelemetry(
        speed = capture(list),
        direction = Direction.SOUTH,
        roadType = captureNullable(roadTypeSlot),
    )
} answers {
    println("Speed: ${list}, roadType: ${roadTypeSlot.captured}")

    RecordingOutcome.RECORDED
}

car.recordTelemetry(speed = 15.0, direction = Direction.NORTH, null) // prints Speed: 15.0, roadType: null
car.recordTelemetry(speed = 16.0, direction = Direction.SOUTH, RoadType.HIGHWAY) // prints Speed: [16.0], roadType: HIGHWAY

verifyOrder {
    car.recordTelemetry(speed = or(15.0, 16.0), direction = any(), roadType = null)
    car.recordTelemetry(speed = 16.0, direction = any(), roadType = RoadType.HIGHWAY)
}

confirmVerified(car)

Verification atLeast, atMost or exactly times

You can check the call count with the atLeast, atMost or exactly parameters:

val car = mockk<Car>(relaxed = true)

car.accelerate(fromSpeed = 10, toSpeed = 20)
car.accelerate(fromSpeed = 10, toSpeed = 30)
car.accelerate(fromSpeed = 20, toSpeed = 30)

// all pass
verify(atLeast = 3) { car.accelerate(allAny()) }
verify(atMost  = 2) { car.accelerate(fromSpeed = 10, toSpeed = or(20, 30)) }
verify(exactly = 1) { car.accelerate(fromSpeed = 10, toSpeed = 20) }
verify(exactly = 0) { car.accelerate(fromSpeed = 30, toSpeed = 10) } // means no calls were performed

confirmVerified(car)

Or you can use verifyCount:

val car = mockk<Car>(relaxed = true)

car.accelerate(fromSpeed = 10, toSpeed = 20)
car.accelerate(fromSpeed = 10, toSpeed = 30)
car.accelerate(fromSpeed = 20, toSpeed = 30)

// all pass
verifyCount { 
    (3..5) * { car.accelerate(allAny(), allAny()) } // same as verify(atLeast = 3, atMost = 5) { car.accelerate(allAny(), allAny()) }
    1 * { car.accelerate(fromSpeed = 10, toSpeed = 20) } // same as verify(exactly = 1) { car.accelerate(fromSpeed = 10, toSpeed = 20) }
    0 * { car.accelerate(fromSpeed = 30, toSpeed = 10) } // same as verify(exactly = 0) { car.accelerate(fromSpeed = 30, toSpeed = 10) }
}

confirmVerified(car)

Verification order

  • verifyAll verifies that all calls happened without checking their order.
  • verifySequence verifies that the calls happened in a specified sequence.
  • verifyOrder verifies that calls happened in a specific order.
  • wasNot Called verifies that the mock (or the list of mocks) was not called at all.
class MockedClass {
    fun sum(a: Int, b: Int) = a + b
}

val obj = mockk<MockedClass>()
val slot = slot<Int>()

every {
    obj.sum(any(), capture(slot))
} answers {
    1 + firstArg<Int>() + slot.captured
}

obj.sum(1, 2) // returns 4
obj.sum(1, 3) // returns 5
obj.sum(2, 2) // returns 5

verifyAll {
    obj.sum(1, 3)
    obj.sum(1, 2)
    obj.sum(2, 2)
}

verifySequence {
    obj.sum(1, 2)
    obj.sum(1, 3)
    obj.sum(2, 2)
}

verifyOrder {
    obj.sum(1, 2)
    obj.sum(2, 2)
}

val obj2 = mockk<MockedClass>()
val obj3 = mockk<MockedClass>()
verify {
    listOf(obj2, obj3) wasNot Called
}

confirmVerified(obj)

Verification confirmation

To double-check that all calls were verified by verify... constructs, you can use confirmVerified:

confirmVerified(mock1, mock2)

It doesn't make much sense to use it for verifySequence and verifyAll, as these verification methods already exhaustively cover all calls with verification.

It will throw an exception if there are some calls left without verification.

Some calls can be excluded from this confirmation, check the next section for more details.

val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK
every { car.drive(Direction.SOUTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK
car.drive(Direction.SOUTH) // returns OK

verify {
    car.drive(Direction.SOUTH)
    car.drive(Direction.NORTH)
}

confirmVerified(car) // makes sure all calls were covered with verification

Unnecessary stubbing

Because clean & maintainable test code requires zero unnecessary code, you can ensure that there is no unnecessary stubs.

checkUnnecessaryStub(mock1, mock2)

It will throw an exception if there are some declared calls on the mocks that are not used by the tested code. This can happen if you have declared some really unnecessary stubs or if the tested code doesn't call an expected one.

Recording exclusions

To exclude unimportant calls from being recorded, you can use excludeRecords:

excludeRecords { mock.operation(any(), 5) }

All matching calls will be excluded from recording. This may be useful if you are using exhaustive verification: verifyAll, verifySequence or confirmVerified.

val car = mockk<Car>()

every { car.drive(Direction.NORTH) } returns Outcome.OK
every { car.drive(Direction.SOUTH) } returns Outcome.OK

excludeRecords { car.drive(Direction.SOUTH) }

car.drive(Direction.NORTH) // returns OK
car.drive(Direction.SOUTH) // returns OK

verify {
    car.drive(Direction.NORTH)
}

confirmVerified(car) // car.drive(Direction.SOUTH) was excluded, so confirmation is fine with only car.drive(Direction.NORTH)

Verification timeout

To verify concurrent operations, you can use timeout = xxx:

mockk<MockCls> {
    every { sum(1, 2) } returns 4

    Thread {
        Thread.sleep(2000)
        sum(1, 2)
    }.start()

    verify(timeout = 3000) { sum(1, 2) }
}

This will wait until one of two following states: either verification is passed or the timeout is reached.

Returning Unit

If a function returns Unit, you can use the justRun construct:

class MockedClass {
    fun sum(a: Int, b: Int): Unit {
        println(a + b)
    }
}

val obj = mockk<MockedClass>()

justRun { obj.sum(any(), 3) }

obj.sum(1, 1)
obj.sum(1, 2)
obj.sum(1, 3)

verify {
    obj.sum(1, 1)
    obj.sum(1, 2)
    obj.sum(1, 3)
}

Other ways to write justRun { obj.sum(any(), 3) }:

  • every { obj.sum(any(), 3) } just Runs
  • every { obj.sum(any(), 3) } returns Unit
  • every { obj.sum(any(), 3) } answers { Unit }

Coroutines

To mock coroutines you need to add another dependency to the support library.

Gradle
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:x.x"
Maven
<dependency>
    <groupId>org.jetbrains.kotlinx</groupId>
    <artifactId>kotlinx-coroutines-core</artifactId>
    <version>x.x</version>
    <scope>test</scope>
</dependency>

Then you can use coEvery, coVerify, coMatch, coAssert, coRun, coAnswers or coInvoke to mock suspend functions.

val car = mockk<Car>()

coEvery { car.drive(Direction.NORTH) } returns Outcome.OK

car.drive(Direction.NORTH) // returns OK

coVerify { car.drive(Direction.NORTH) }

And to simulate a never returning suspend function, you can use coJustAwait:

runTest {
    val car = mockk<Car>()

    coJustAwait { car.drive(any()) } // car.drive(...) will never return

    val job = launch(UnconfinedTestDispatcher()) {
        car.drive(Direction.NORTH)
    }

    coVerify { car.drive(Direction.NORTH) }

    job.cancelAndJoin() // Don't forget to cancel the job
}

Note: there is a known issue if using a spy with a suspending function: #554

Top Level functions

Kotlin lets you declare functions that don’t belong to any class or object, called top-level functions. These calls are translated to static methods in jvm environments, and a special Java class is generated to hold the functions. These top-level functions can be mocked using mockkStatic. You just need to import the function and pass a reference as the argument:

import com.cars.buildCar

val testCar = Car()
mockkStatic(::buildCar)
every { buildCar() } returns testCar

assertEquals(testCar, buildCar())

verify { buildCar() }

Mocking a function will clear any existing mocks of other functions declared in the same file, equivalent to calling clearStaticMockk on the generated enclosing class.

Extension functions

There are three types of extension function in Kotlin:

  • class-wide
  • object-wide
  • module-wide

For an object or a class, you can mock extension functions just by creating a regular mockk:

data class Obj(val value: Int)

class Ext {
    fun Obj.extensionFunc() = value + 5
}

with(mockk<Ext>()) {
    every {
        Obj(5).extensionFunc()
    } returns 11

    assertEquals(11, Obj(5).extensionFunc())

    verify {
        Obj(5).extensionFunc()
    }
}

To mock module-wide extension functions you need to build mockkStatic(...) with the module's class name as an argument. For example "pkg.FileKt" for module File.kt in the pkg package.

data class Obj(val value: Int)

// declared in File.kt ("pkg" package)
fun Obj.extensionFunc() = value + 5

mockkStatic("pkg.FileKt")

every {
    Obj(5).extensionFunc()
} returns 11

assertEquals(11, Obj(5).extensionFunc())

verify {
    Obj(5).extensionFunc()
}

In jvm environments you can replace the class name with a function reference:

mockkStatic(Obj::extensionFunc)

Note that this will mock the whole pkg.FileKt class, and not just extensionFunc.

This syntax also applies for extension properties:

val Obj.squareValue get() = value * value

mockkStatic(Obj::squareValue)

If @JvmName is used, specify it as a class name.

KHttp.kt:

@file:JvmName("KHttp")

package khttp
// ... KHttp code 

Testing code:

mockkStatic("khttp.KHttp")

Sometimes you need to know a little bit more to mock an extension function. For example the extension function File.endsWith() has a totally unpredictable classname:

mockkStatic("kotlin.io.FilesKt__UtilsKt")
every { File("abc").endsWith(any<String>()) } returns true
println(File("abc").endsWith("abc"))

This is standard Kotlin behaviour that may be unpredictable. Use Tools -> Kotlin -> Show Kotlin Bytecode or check .class files in JAR archive to detect such names.

Varargs

From version 1.9.1, more extended vararg handling is possible:

interface ClsWithManyMany {
    fun manyMany(vararg x: Any): Int
}

val obj = mockk<ClsWithManyMany>()

every { obj.manyMany(5, 6, *varargAll { it == 7 }) } returns 3

println(obj.manyMany(5, 6, 7)) // 3
println(obj.manyMany(5, 6, 7, 7)) // 3
println(obj.manyMany(5, 6, 7, 7, 7)) // 3

every { obj.manyMany(5, 6, *anyVararg(), 7) } returns 4

println(obj.manyMany(5, 6, 1, 7)) // 4
println(obj.manyMany(5, 6, 2, 3, 7)) // 4
println(obj.manyMany(5, 6, 4, 5, 6, 7)) // 4

every { obj.manyMany(5, 6, *varargAny { nArgs > 5 }, 7) } returns 5

println(obj.manyMany(5, 6, 4, 5, 6, 7)) // 5
println(obj.manyMany(5, 6, 4, 5, 6, 7, 7)) // 5

every {
    obj.manyMany(5, 6, *varargAny {
        if (position < 3) it == 3 else it == 4
    }, 7)
} returns 6

println(obj.manyMany(5, 6, 3, 4, 7)) // 6
println(obj.manyMany(5, 6, 3, 4, 4, 7)) // 6

Private functions mocking / dynamic calls

IF you need to mock private functions, you can do it via a dynamic call.

class Car {
    fun drive() = accelerate()

    private fun accelerate() = "going faster"
}

val mock = spyk<Car>(recordPrivateCalls = true)

every { mock["accelerate"]() } returns "going not so fast"

assertEquals("going not so fast", mock.drive())

verifySequence {
    mock.drive()
    mock["accelerate"]()
}

If you want to verify private calls, you should create a spyk with recordPrivateCalls = true

Additionally, a more verbose syntax allows you to get and set properties, combined with the same dynamic calls:

val mock = spyk(Team(), recordPrivateCalls = true)

every { mock getProperty "speed" } returns 33
every { mock setProperty "acceleration" value less(5) } just runs
justRun { mock invokeNoArgs "privateMethod" }
every { mock invoke "openDoor" withArguments listOf("left", "rear") } returns "OK"

verify { mock getProperty "speed" }
verify { mock setProperty "acceleration" value less(5) }
verify { mock invoke "openDoor" withArguments listOf("left", "rear") }

Property backing fields

You can access the backing fields via fieldValue and use value for the value being set.

Note: in the examples below, we use propertyType to specify the type of the fieldValue. This is needed because it is possible to capture the type automatically for the getter. Use nullablePropertyType to specify a nullable type.

val mock = spyk(MockCls(), recordPrivateCalls = true)

every { mock.property } answers { fieldValue + 6 }
every { mock.property = any() } propertyType Int::class answers { fieldValue += value }
every { mock getProperty "property" } propertyType Int::class answers { fieldValue + 6 }
every { mock setProperty "property" value any<Int>() } propertyType Int::class answers  { fieldValue += value }
every {
    mock.property = any()
} propertyType Int::class answers {
    fieldValue = value + 1
} andThen {
    fieldValue = value - 1
}

Multiple interfaces

Adding additional behaviours via interfaces and stubbing them:

val spy = spyk(System.out, moreInterfaces = arrayOf(Runnable::class))

spy.println(555)

every {
    (spy as Runnable).run()
} answers {
    (self as PrintStream).println("Run! Run! Run!")
}

val thread = Thread(spy as Runnable)
thread.start()
thread.join()

Mocking Nothing

Nothing special here. If you have a function returning Nothing:

fun quit(status: Int): Nothing {
    exitProcess(status)
}

Then you can for example throw an exception as behaviour:

every { quit(1) } throws Exception("this is a test")

Clearing vs Unmocking

  • clear - deletes the internal state of objects associated with a mock, resulting in an empty object
  • unmock - re-assigns transformation of classes back to original state prior to mock

Scoped mocks

A Scoped mock is a mock that automatically unmocks itself after the code block passed as a parameter has been executed. You can use the mockkObject, mockkStatic and mockkConstructor functions.

object ObjBeingMocked {
 fun add(a: Int, b: Int) = a + b
}

// ObjBeingMocked will be unmocked after this scope
mockkObject(ObjBeingMocked) {
 assertEquals(3, ObjBeingMocked.add(1, 2))
 every { ObjBeingMocked.add(1, 2) } returns 55
 assertEquals(55, ObjBeingMocked.add(1, 2))
}

Matcher extensibility

A very simple way to create new matchers is by attaching a function to MockKMatcherScope or MockKVerificationScope and using the match function:

fun MockKMatcherScope.seqEq(seq: Sequence<String>) = match<Sequence<String>> {
    it.toList() == seq.toList()
}

It's also possible to create more advanced matchers by implementing the Matcher interface.

Custom matchers

Example of a custom matcher that compares list without order:

@Test
fun test() {
    class MockCls {
        fun op(a: List<Int>) = a.reversed()
    }

    val mock = mockk<MockCls>()

    every { mock.op(any()) } returns listOf(5, 6, 9)

    println(mock.op(listOf(1, 2, 3)))

    verify { mock.op(matchListWithoutOrder(3, 2, 1)) }

}

data class ListWithoutOrderMatcher<T>(
    val expectedList: List<T>,
    val refEq: Boolean
) : Matcher<List<T>> {
    val map = buildCountsMap(expectedList, refEq)

    override fun match(arg: List<T>?): Boolean {
        if (arg == null) return false
        return buildCountsMap(arg, refEq) == map
    }

    private fun buildCountsMap(list: List<T>, ref: Boolean): Map<Any?, Int> {
        val map = mutableMapOf<Any?, Int>()

        for (item in list) {
            val key = when {
                item == null -> nullKey
                refEq -> InternalPlatform.ref(item)
                else -> item
            }
            map.compute(key, { _, value -> (value ?: 0) + 1 })
        }

        return map
    }

    override fun toString() = "matchListWithoutOrder($expectedList)"

    @Suppress("UNCHECKED_CAST")
    override fun substitute(map: Map<Any, Any>): Matcher<List<T>> {
        return copy(expectedList = expectedList.map { map.getOrDefault(it as Any?, it) } as List<T>)
    }

    companion object {
        val nullKey = Any()
    }
}

inline fun <reified T : List<E>, E : Any> MockKMatcherScope.matchListWithoutOrder(
    vararg items: E,
    refEq: Boolean = true
): T = match(ListWithoutOrderMatcher(listOf(*items), refEq))

Reflection matchers

Example using reflection to mock all methods on a builder-style object

val builderFunctions = MyBuilder::class.memberFunctions.filter { it.returnType.classifier == MyBuilder::class }
val builderMock = mockk<MyBuilder> {
  builderFunctions.forEach { func ->
    every {
      val params = listOf<Any?>(builderMock) + func.parameters.drop(1).map { any(it.type.classifier as KClass<Any>) }
      func.call(*params.toTypedArray())
    } answers { 
      this@mockk
    }
  }
}

Settings file

To adjust parameters globally, there are a few settings you can specify in a resource file.

How to use:

  1. Create a io/mockk/settings.properties file in src/main/resources.
  2. Put any of the following options:
relaxed=true|false
relaxUnitFun=true|false
recordPrivateCalls=true|false
stackTracesOnVerify=true|false
stackTracesAlignment=left|center

stackTracesAlignment determines whether to align the stack traces to the center (default), or to the left (more consistent with usual JVM stackTraces).

DSL tables

Here are a few tables to help you master the DSL.

Top level functions

Function Description
mockk<T>(...) builds a regular mock
spyk<T>() builds a spy using the default constructor
spyk(obj) builds a spy by copying from obj
slot creates a capturing slot
every starts a stubbing block
coEvery starts a stubbing block for coroutines
verify starts a verification block
coVerify starts a verification block for coroutines
verifyAll starts a verification block that should include all calls
coVerifyAll starts a verification block that should include all calls for coroutines
verifyOrder starts a verification block that checks the order
coVerifyOrder starts a verification block that checks the order for coroutines
verifySequence starts a verification block that checks whether all calls were made in a specified sequence
coVerifySequence starts a verification block that checks whether all calls were made in a specified sequence for coroutines
excludeRecords exclude some calls from being recorded
confirmVerified confirms that all recorded calls were verified
checkUnnecessaryStub confirms that all recorded calls are used at least once
clearMocks clears specified mocks
registerInstanceFactory allows you to redefine the way of instantiation for certain object
mockkClass builds a regular mock by passing the class as parameter
mockkObject turns an object into an object mock, or clears it if was already transformed
unmockkObject turns an object mock back into a regular object
mockkStatic makes a static mock out of a class, or clears it if it was already transformed
unmockkStatic turns a static mock back into a regular class
clearStaticMockk clears a static mock
mockkConstructor makes a constructor mock out of a class, or clears it if it was already transformed
unmockkConstructor turns a constructor mock back into a regular class
clearConstructorMockk clears the constructor mock
unmockkAll unmocks object, static and constructor mocks
clearAllMocks clears regular, object, static and constructor mocks

Matchers

By default, simple arguments are matched using eq()

Matcher Description
any() matches any argument
any(Class) matches any argument of the give Class (for reflective mocking)
allAny() special matcher that uses any() instead of eq() for matchers that are provided as simple arguments
isNull() checks if the value is null
isNull(inverse=true) checks if the value is not null
ofType(type) checks if the value belongs to the type
match { it.startsWith("string") } matches via the passed predicate
coMatch { it.startsWith("string") } matches via the passed coroutine predicate
matchNullable { it?.startsWith("string") } matches nullable value via the passed predicate
coMatchNullable { it?.startsWith("string") } matches nullable value via the passed coroutine predicate
eq(value) matches if the value is equal to the provided value via the deepEquals function
eq(value, inverse=true) matches if the value is not equal to the provided value via the deepEquals function
neq(value) matches if the value is not equal to the provided value via the deepEquals function
refEq(value) matches if the value is equal to the provided value via reference comparison
refEq(value, inverse=true) matches if the value is not equal to the provided value via reference comparison
nrefEq(value) matches if the value is not equal to the provided value via reference comparison
cmpEq(value) matches if the value is equal to the provided value via the compareTo function
less(value) matches if the value is less than the provided value via the compareTo function
more(value) matches if the value is more than the provided value via the compareTo function
less(value, andEquals=true) matches if the value is less than or equal to the provided value via the compareTo function
more(value, andEquals=true) matches if the value is more than or equal to the provided value via the compareTo function
range(from, to, fromInclusive=true, toInclusive=true) matches if the value is in range via the compareTo function
and(left, right) combines two matchers via a logical and
or(left, right) combines two matchers via a logical or
not(matcher) negates the matcher
capture(slot) captures a Non Nullable value to a CapturingSlot
captureNullable(slot) captures a Nullable value to a CapturingSlot
capture(mutableList) captures a value to a list
captureNullable(mutableList) captures a value to a list together with null values
captureLambda() captures a lambda
captureCoroutine() captures a coroutine
invoke(...) calls a matched argument
coInvoke(...) calls a matched argument for a coroutine
hint(cls) hints the next return type in case it's gotten erased
anyVararg() matches any elements in a vararg
varargAny(matcher) matches if any element matches the matcher
varargAll(matcher) matches if all elements match the matcher
any...Vararg() matches any elements in vararg (specific to primitive type)
varargAny...(matcher) matches if any element matches the matcher (specific to the primitive type)
varargAll...(matcher) matches if all elements match the matcher (specific to the primitive type)

A few special matchers available in verification mode only:

Matcher Description
withArg { code } matches any value and allows to execute some code
withNullableArg { code } matches any nullable value and allows to execute some code
coWithArg { code } matches any value and allows to execute some coroutine code
coWithNullableArg { code } matches any nullable value and allows to execute some coroutine code

Validators

Validator Description
verify { mock.call() } Do unordered verification that a call was performed
verify(inverse=true) { mock.call() } Do unordered verification that a call was not performed
verify(atLeast=n) { mock.call() } Do unordered verification that a call was performed at least n times
verify(atMost=n) { mock.call() } Do unordered verification that a call was performed at most n times
verify(exactly=n) { mock.call() } Do unordered verification that a call was performed exactly n times
verifyAll { mock.call1(); mock.call2() } Do unordered verification that only the specified calls were executed for the mentioned mocks
verifyOrder { mock.call1(); mock.call2() } Do verification that the sequence of calls went one after another
verifySequence { mock.call1(); mock.call2() } Do verification that only the specified sequence of calls were executed for the mentioned mocks
verify { mock wasNot Called } Do verification that a mock was not called
verify { listOf(mock1, mock2) wasNot Called } Do verification that a list of mocks were not called

Answers

An Answer can be followed up by one or more additional answers.

Answer Description
returns value specify that the matched call returns a specified value
returnsMany list specify that the matched call returns a value from the list, with subsequent calls returning the next element
returnsArgument(n) specify that the matched call returns the nth argument of that call
throws ex specify that the matched call throws an exception
throwsMany list specify that the matched call throws an exception from the list, with subsequent calls throwing the next exception
answers { code } specify that the matched call answers with a code block scoped with answer scope
coAnswers { code } specify that the matched call answers with a coroutine code block with answer scope
answers answerObj specify that the matched call answers with an Answer object
answers { nothing } specify that the matched call answers null
just Runs specify that the matched call is returning Unit (returns null)
just Awaits specify that the matched call never returns (available since v1.13.3)
propertyType Class specify the type of the backing field accessor
nullablePropertyType Class specify the type of the backing field accessor as a nullable type

Additional answer(s)

A next answer is returned on each consequent call and the last value is persisted. So this is similar to the returnsMany semantics.

Additional answer Description
andThen value specify that the matched call returns one specified value
andThenMany list specify that the matched call returns a value from the list, with subsequent calls returning the next element
andThenThrows ex specify that the matched call throws an exception
andThenThrowsMany ex specify that the matched call throws an exception from the list, with subsequent calls throwing the next exception
andThen { code } specify that the matched call answers with a code block scoped with answer scope
coAndThen { code } specify that the matched call answers with a coroutine code block with answer scope
andThenAnswer answerObj specify that the matched call answers with an Answer object
andThen { nothing } specify that the matched call answers null
andThenJust Runs specify that the matched call is returning Unit (available since v1.12.2)
andThenJust Awaits specify that the matched call is never returning (available since v1.13.3)

Answer scope

Parameter Description
call a call object that consists of an invocation and a matcher
invocation contains information regarding the actual function invoked
matcher contains information regarding the matcher used to match the invocation
self reference to the object invocation made
method reference to the function invocation made
args reference to the invocation arguments
nArgs number of invocation arguments
arg(n) nth argument
firstArg() first argument
secondArg() second argument
thirdArg() third argument
lastArg() last argument
captured() the last element in the list for convenience when capturing to a list
lambda<...>().invoke() call the captured lambda
coroutine<...>().coInvoke() call the captured coroutine
nothing null value for returning nothing as an answer
fieldValue accessor to the property backing field
fieldValueAny accessor to the property backing field with Any? type
value value being set, cast to the same type as the property backing field
valueAny value being set, with Any? type
callOriginal calls the original function

Vararg scope

Parameter Description
position the position of an argument in a vararg array
nArgs overall count of arguments in a vararg array

Funding

You can also support this project by becoming a sponsor. Your logo will show up here with a link to your website.

Sponsors

Backers

Thank you to all our backers! 🙏

Contributors

This project exists thanks to all the people who contribute.

Getting Help

To ask questions, please use Stack Overflow or Gitter.

To report bugs, please use the GitHub project.

mockk's People

Contributors

agebhar1 avatar asemy avatar bossm0n5t3r avatar dekan avatar drazen04 avatar freddeschenes avatar geekiyer avatar ghackett avatar gmazzo avatar hrach avatar iainism avatar k163377 avatar kris87us avatar krocard avatar kshired avatar kubode avatar leocolman avatar leonra avatar milgner avatar nwuensche avatar oleksiyp avatar qoomon avatar raibaz avatar sandhya2902 avatar sergey-volkov-lm avatar simonmarquis avatar t45k avatar vkanash avatar ygaller avatar zhaohuazeng-at avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mockk's Issues

spyk broken for class hierarchies

Thanks, mockk is looking really promising!
Howver, it seems like there are a few issues with spy when the object inherits from a base class.
Some examples:

the 'logger' fields can be anything, but it is a pretty common pattern, and one where you may have private final fields with the same name in a class and its superclass.

        open class BaseTest(val someReference:String) {
            private var logger: org.slf4j.Logger = LoggerFactory.getLogger(BaseTest::class.java)
            open fun doLog() {
                logger.info("Base $someReference")
            }
        }

        class SpyTest() : BaseTest("A spy"){
            private var logger: org.slf4j.Logger = LoggerFactory.getLogger(SpyTest::class.java)
            override fun doLog() {
                logger.info("spyTest")
            }
        }

        val spyObj = spyk<BaseTest>(SpyTest()) // this breaks.
//        val spyObj = spyk<SpyTest>(SpyTest()) // uncomment this as a semi-workaround
        every {
            spyObj.doLog()
        } just Runs.apply{println("Intercepted")}
        // but superclass fields are not set correctly, so this fails too:
        assert(spyObj.someReference != null)
        spyObj.doLog()

Bug: Mocking Lambda NullpointerException in Robolectric

When a class receives a lambda as a parameter, one might want to mock the received lambda, so it may be possible to verify its behaviour.

But, unfortunately, there's a NullPointerException when trying to mock a lambda:

 class LambdaClass(val lambda: (Int) -> Unit) {
        
        fun doStuff() {
            lambda(5)
        }
    }
    
    @Test
    fun testLambda() {
        val mockedLambda: (Int) -> Unit = mockk()
        val klass = LambdaClass(mockedLambda)
        klass.doStuff()
        
        verify { mockedLambda(5) }
    }

java.lang.NullPointerException
at io.mockk.proxy.MockKProxyInterceptor.intercept(MockKProxyInterceptor.java:16)
at kotlin.jvm.functions.Function1$ByteBuddy$5kfph9ys$ByteBuddy$wGXaV9Md.invoke(Unknown Source)
at my.package.Playground$LambdaClass.doStuff(Playground.kt:26)
at my.package.Playground.testLambda(Playground.kt:34)

Capturing in private suspend functions does not work

For example given the following class:

class MyClass {

  private suspend myPrivateCall(arg1) {
  
   }

}

And then in the test:

val myClassSpy = spyk(MyClass())

every { myClassSpy["myPrivateCall"](arg1) } returns "something"

Throws: java.lang.IllegalArgumentException: Callable expects X arguments, but Y were provided.

This only happens if the function is suspend private function.

spykk complaining it couldn’t initialize

@yannickvg let's move this to another open thread.

So your report:

Was trying out the spyk() but with less success. I also use dagger, so in
the class i want to spy i have a primary constructor with some dependencies.
So obviously it complained it couldn’t initialize.

I tried doing what i would do in java and made 2 constructors, one with
dependencies, one without and created lateinit var fields for the
dependencies, but then i get errors that the properties have not been
initialized.

So still figuring out how to use the spy with mandatory 

Can you send exception dumps of those complains?

Verify with any ignores exactly

Specifying exactly=0 on a verify where an any() matcher is used results in a verification failure when a different call does happen on the mock . This should not be an error as the call did specified did not happen

Example from your io.mockk.it.VerifyAtLeastAtMostExactlyTest class.

class MockCls {
        fun op(a: Int) = a + 1
        fun op2(a: Int, b: Int) = a + b
    }

val mock = mockk<MockCls>()

@Test
    fun exactlyZeroWithAny() {
        doCalls()

        verify(exactly = 0) {
            mock.op2(3, any())
        }
    }

fun doCalls() {
        every { mock.op(0) } throws RuntimeException("test")
        every { mock.op(1) } returnsMany listOf(1, 2, 3)
        every { mock.op2(2, 1) } returns 3

        assertFailsWith(RuntimeException::class) {
            mock.op(0)
        }

        assertEquals(1, mock.op(1))
        assertEquals(2, mock.op(1))
        assertEquals(3, mock.op(1))
        assertEquals(3, mock.op(1))
        assertEquals(3, mock.op2(2, 1))
    }

Error:

java.lang.AssertionError: Verification failed: call 1 of 1: MockCls(#387).op2(eq(3), any())). Only one matching call to MockCls(#387)/op2(Int, Int) happened, but arguments are not matching:
[0]: argument: 2, matcher: eq(3), result: -
[1]: argument: 1, matcher: any(), result: +

NoClassDefFoundError: KClasses

When running my tests with version 1.4, I get the following error on all my tests:

java.lang.NoClassDefFoundError: kotlin/reflect/full/KClasses
	at io.mockk.impl.MockFactoryImpl.mockk(Factory.kt:27)

Exactly the same tests with version 1.3 works fine.

Cannot objectMockk inline function

I tried to objectMockk an inline function of an object and it didn't seem to work.

I did sth like

`
@BeforeAll
fun beforeTests() {

    objectMockk(MockObj).mock()

    every { MockObj.getSth<Room>(1) } returns 1
}

`
and the getSth is simply like:

inline fun <reified T> getSth(): String { return (T::class.annotations.find { it is MongoDBCollection } as MongoDBCollection).name }

and it throws

=> io.mockk.MockKException: Missing calls inside every { ... } block

Is that mocking of inline function is not supported?

Thanks.

any() matcher for java Class parameter fails with IllegalAccessError

if I have a method parameter that is of type java.lang.Class<?> like:

public boolean isRegistered(Class<?> componentClass);

or in Kotlin:

fun gimmeJavaClass(klass: Class<*>): Boolean = true

then the any() matcher causes a java.lang.Class exception:

java.lang.IllegalAccessError: java.lang.Class

	at sun.reflect.GeneratedSerializationConstructorAccessor12.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
	at io.mockk.proxy.MockKProxyMaker.newEmptyInstance(MockKProxyMaker.java:230)
	at io.mockk.proxy.MockKProxyMaker.instance(MockKProxyMaker.java:63)
	at io.mockk.impl.instantiation.JvmInstantiator$instantiate$2.invoke(JvmInstantiator.kt:16)
	at io.mockk.impl.instantiation.AbstractInstantiator.instantiateViaInstanceFactoryRegistry(AbstractInstantiator.kt:17)
	at io.mockk.impl.instantiation.JvmInstantiator.instantiate(JvmInstantiator.kt:15)
	at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1$1.invoke(RecordingState.kt:46)
	at io.mockk.impl.instantiation.JvmAnyValueGenerator$anyValue$1.invoke(JvmAnyValueGenerator.kt:24)
	at io.mockk.impl.instantiation.AnyValueGenerator.anyValue(AnyValueGenerator.kt:27)
	at io.mockk.impl.instantiation.JvmAnyValueGenerator.anyValue(JvmAnyValueGenerator.kt:20)
	at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1.invoke(RecordingState.kt:45)
	at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:20)
	at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:44)
	at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:47)
	at io.mockk.MockKTestSuite$1$11$1.invoke(MockKTestSuite.kt:607)
	at io.mockk.MockKTestSuite$1$11$1.invoke(MockKTestSuite.kt:10)
	at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:22)
	at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:31)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:25)

Here is a test case:

  1. Modify your io.mockk.MockCls class in CommonCallRecorderTest to add
fun gimmeJavaClass(klass: Class<*>): Boolean = true
  1. Add this test. It will fail:
"any class" {
        every { mock.gimmeJavaClass(any()) }.returns(false)
        assertEquals(false, mock.gimmeJavaClass(Long::class.java))
    }

Feature Request: Return sensible default Answers for Every

Currently Mockk is designed to throw an exception if every is not called with an accompanying Answer. This means that every mock interaction must be accounted for when writing tests. It would be convenient if every assumed a sensible default Answer.

Consider the following code:
Production:

class LocalBusAware(val eventBus: EventBus) {
 fun open() {
   if (!eventBus.isRegistered(this)) {
        eventBus.register(this)
   }
 }
}

Test (current state):

    @Test
    fun openRegistersWithTheBus() {
        val eventBus = mockk<EventBus>()
        val subject = LocalBusAware(eventBus)
        every { eventBus.isRegistered(subject) } returns false
        every {eventBus.register(subject)} returns Unit
        subject.open()

        verify {eventBus.register(subject)}
    }

In this example isRegistered() and register() must both have defined every calls with specific returns values. In more complex scenarios this can be extremely cumbersome, as every mock action must be accounted for.

A more preferable test might be something like this:

    @Test
    fun openRegistersWithTheBus() {
        val eventBus = mockk<EventBus>() 
        val subject = LocalBusAware(eventBus)
        subject.open()

        verify {eventBus.register(subject)}
    }

In this example isRegistered() returns false by default, and does not need to be explicitly defined, and register() returns Unit (and it is part of the verify sequence), so it does not need to be explicitly defined either.

Our tests can be much more focused, only requiring interactions that we care about to execute our scenario. This would also be more in line with what frameworks such as Mockito do, and I think it would help drive adoption of Mockk from those frameworks.

Thoughts?

Show stacktrace of undesirable call in `verify` error message

Currently, if verify block throws an assert because you have undesired mock method call you cannot detect who called this method, so the only option to debug this case.

Currently I see something like:
java.lang.AssertionError: Verification failed: call 1 of 1: SomeClass(#10).someMethid()). 2 matching calls found, but needs at least 0 and at most 1 calls

But would be very good to have something like:

java.lang.AssertionError: Verification failed: call 1 of 1: SomeClass(#10).someMethid()). 2 matching calls found, but needs at least 0 and at most 1 calls
Call 1: SomeOtherClass:123 // Class with line number
Call 2: OneMoreClass:24

Broken JDK7 compatibility

Mockk 1.7.9 (and all other versions I guess) is currently unable to run under JDK7 due to forEach lambda in JvmAutoHinter for example.

Constructor: spyk doesn't register calls from constructor

Spy verification doesn't work for methods called from constructor:

class TestClass {
  init { test() }
  fun test() {}
}
...
val spyed = spyk(TestClass())
...
verify { spyed.test() }

I'm kinda novice at testing but I do understand one could create another constructor for testing purpose without some kind of setup method call. I just wonder, is this feature out of scope or planned for future?

Not able to mock for return type as Arrow#Either

I am trying mock a method call which returns of Either type of Arrow Library. But i am getting below exception when writing the Mock behaviour
code : every { /*somemethod call*/ }.returns(Either.left(/*Some object*/)

Exception
kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Incorrect resolution sequence for Java field public final val isLeft: kotlin.Boolean defined in arrow.core.Either$ByteBuddy$0FhSn1dn[JavaPropertyDescriptor@3c49fab6] (source = null)
Is this something to be fixed in the library or its not at all support shield classes ?

how to match varags?

I don't see how to create a mock match for a function accepting varargs. Is that supported? Thanks.

Bug: callOriginal() for default interface methods is not working

import io.mockk.every
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify
import javax.xml.crypto.Data

data class ItemData(val id: Int)

interface Database {
    fun insertItems(items: List<ItemData>)
    fun deleteItems(items: List<ItemData>)
    fun runTransaction(alsoDelete: Boolean) {
        insertItems(listOf(ItemData(id = 1), ItemData(id = 2), ItemData(id = 3)))
        if (alsoDelete)
            deleteItems(listOf(ItemData(id = 4), ItemData(id = 5), ItemData(id = 6)))
    }
}


fun main(args: Array<String>) {
    val x = mockk<Database>()
    every { x.runTransaction(any()) } answers { callOriginal() }
    x.runTransaction(alsoDelete = true)
    verify { x.insertItems(listOf(ItemData(id = 1), ItemData(id = 2), ItemData(id = 3))) }
}

Should work

How to run it with Android Instrumentation Tests

I've been trying to run mockk with androi instrumentation test but no success.
I've added testCompile "io.mockk:mockk:1.7.10"
To my build.gradle
And I was able to run it perfectly as a unit test.
But if I try to run as an Instrumentation Test, I get a unresolved reference in io.mockk.*

If I add :
androidTestCompile "io.mockk:mockk:1.7.10"

I was able to build it, doesnt get the unresolved reference anymore, but when I run the test I got:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/lang/instrument/ClassFileTransformer;

Is there something I'm doing wrong, I really wish to use mockk it with android instrumentation tests.

Here is my Test section in my build.gradle

`

testCompile 'org.mockito:mockito-core:2.7.22'

androidTestCompile 'org.mockito:mockito-android:2.7.22'

androidTestCompile 'io.mockk:mockk:1.7.10'

testCompile 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0'

testImplementation 'org.hamcrest:hamcrest-library:1.3'

testImplementation "com.squareup.retrofit2:retrofit-mock:${retrofitLibVersion}"

testImplementation 'org.mockito:mockito-inline:2.13.0'

testCompile ('org.threeten:threetenbp:1.3.2'){
    exclude group:'com.jakewharton.threetenabp', module:'threetenabp'
}
testCompile 'junit:junit:4.12'
testCompile "io.mockk:mockk:1.7.10"

`

StackOverflowException with HashMap

I think this might be related to mockito/mockito#818 as maybe it was ported from the culprit over there.
I'm using 1.7.8 and actually in my case I'm not mocking a HashMap, but returning one from an every block

 val blob : CloudBlockBlob = mockk() // from azure-storage-java  
 val metadata : HashMap<String?,String?> = hashMapOf()
 every { blob.metadata } returns metadata

The StackOverflowException occurs when blob calls metadata. I don't know why HashMap is getting mocked though.
Honestly I don't know what is happening but that mockito bug looked too similar to ignore

Exception in thread "main" java.lang.StackOverflowError
at java.lang.Class.getDeclaredMethod(Class.java:2127)
at java.util.HashMap.get(HashMap.java:556)
at sun.reflect.Reflection.filterMethods(Reflection.java:291)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)

Missing equivalent for Mockito annotation @InjectMocks

Please add equivalent for annotation Mockito @JnjectMocks
Or is there any other way to automatically inject to @Inject annotated field

class UseCase {
  @Inject
  lateinit var service: Service
}

Currently I have to manually set it up

 private lateinit var useCase: UseCase

  @Before
  fun setUp() {
    MockKAnnotations.init(this)

    useCase = UseCase()
    useCase.service = service
  }

Missing Feature? Mocking dynamic type

Use Case: In mockito I was doing this:

private void assertRequestClassWasUsed(final Class<? extends AbstractRequest> requestKlass, Runnable doIt, Consumer<QueueWriter> verification) {
        final QueueWriter queueWriter = expectedQueueWriter.get(requestKlass);
        assertThat(queueWriter).as("Could not find queuewriter for payload %s", requestKlass.getCanonicalName()).isNotNull();
        final AbstractRequest request = (AbstractRequest)mock(requestKlass);  //<-- This
        when(queueWriter.getName()).thenReturn(QUEUE_NAME);
        when(message.getPayload()).thenReturn(request);
        when(receivedMessage.getPayload()).thenReturn(request);
        doIt.run();
        verification.accept(queueWriter);
        Mockito.reset(primaryQueueWriter, refreshQueueWriter, harvestQueueWriter, createQueueWriter);

I cannot figure out a way in mockk to do the equivalent of mock(requestClass) where the class is not known at compile time. I fully admit that I am missing something here.

Dex issue with mockk for instrumentation test environment

I have a use case with using Kotlin classes in my UI tests. To mock them I have opted with mockk, because of the class finalization that mockk gracefully solves.

The problem is that it lacks some setup. I am facing dex issue. I do suspect that it is connected to the same problem mockito library had. It was solved by LinkedIn and their dexmaker solution. Is there any way we can run mockk on the emulator or real device dex environment?

Caused by: java.lang.ClassNotFoundException: Didn't find class "java.lang.instrument.ClassFileTransformer" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/system/framework/android.test.mock.jar"],nativeLibraryDirectories=[/data/app/my.app.test-35h1VdSJ4oyoucfymSsugg==/lib/arm64, /data/app/my.app.staging.debug-7njk-OasH4iMH8Dkfhr-4A==/lib/arm64, /data/app/my.app.test-35h1VdSJ4oyoucfymSsugg==/base.apk!/lib/arm64-v8a, /data/app/my.app.staging.debug-7njk-OasH4iMH8Dkfhr-4A==/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)

libattach.dylib loaded twice

Tests run: 22, Failures: 0, Errors: 10, Skipped: 0, Time elapsed: 0.213 s <<< FAILURE! - in hm.binkley.labs.skratch.knapsack.ValueSetMockTest
shouldStartZeroSized()  Time elapsed: 0.013 s  <<< ERROR!
java.lang.ExceptionInInitializerError
	at hm.binkley.labs.skratch.knapsack.LayersMockTest.<init>(LayersMockTest.kt:57)
Caused by: java.lang.IllegalStateException: Error during attachment using: io.mockk.shadowed.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound@2c3c9e65
	at hm.binkley.labs.skratch.knapsack.LayersMockTest.<init>(LayersMockTest.kt:57)
Caused by: java.lang.reflect.InvocationTargetException
	at hm.binkley.labs.skratch.knapsack.LayersMockTest.<init>(LayersMockTest.kt:57)
Caused by: java.lang.UnsatisfiedLinkError: Native Library /Library/Java/JavaVirtualMachines/jdk1.8.0_152.jdk/Contents/Home/jre/lib/libattach.dylib already loaded in another classloader
	at hm.binkley.labs.skratch.knapsack.LayersMockTest.<init>(LayersMockTest.kt:57)

staticMockk to Mock Companion Object?

Hello,
Can I use staticMockk function to mock a companion object?
I got something like
class StreamingStore private constructor() {

companion object {
private val store: ReadOnlyKeyValueStore<String, String>//kafka readOnlyStore

get(key:UUID): DomainObject{
val message = store.get(key.toString())
//logic
return DomainObject
}
}

On my test I tried
staticMockk("package.StreamingStore").use {
every {
get(uuid.toString())
} returns DomainObject(UUID.randomUUID())
}
but it's not working

Mocking data classes causes MockKException

I have a number of data classes and I cannot seem to mock them as they do not have a non arg constructor. Kotlin does not allow this. If I convert it to a normal class then it seems to be able to mock the class.

Im using JUnit 5 with @ExtendWith(MockKExtension::class)

io.mockk.MockKException: No matching constructors found:
constructor(entity : com.google.cloud.datastore.Entity = )
constructor(id : java.util.UUID = , firstName : kotlin.String = , lastName : kotlin.String = , email : kotlin.String = , schoolId : java.util.UUID = , classId : java.util.UUID = , password : kotlin.String = )

at io.mockk.impl.annotations.MockInjector.constructorInjection(MockInjector.kt:20)
at io.mockk.impl.annotations.JvmMockInitializer.doInjection(JvmMockInitializer.kt:62)
at io.mockk.impl.annotations.JvmMockInitializer.initMock(JvmMockInitializer.kt:40)
at io.mockk.impl.annotations.JvmMockInitializer.initAnnotatedMocks(JvmMockInitializer.kt:17)
at io.mockk.junit5.MockKExtension.postProcessTestInstance(MockKExtension.kt:93)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeTestInstancePostProcessors$3(ClassTestDescriptor.java:215)
at org.junit.jupiter.engine.descriptor.JupiterTestDescriptor.executeAndMaskThrowable(JupiterTestDescriptor.java:141)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$invokeTestInstancePostProcessors$4(ClassTestDescriptor.java:215)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:743)
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeTestInstancePostProcessors(ClassTestDescriptor.java:214)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateAndPostProcessTestInstance(ClassTestDescriptor.java:196)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$0(ClassTestDescriptor.java:185)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$1(ClassTestDescriptor.java:189)
at java.util.Optional.orElseGet(Optional.java:267)
at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.lambda$testInstanceProvider$2(ClassTestDescriptor.java:188)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:81)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:58)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.prepare(HierarchicalTestExecutor.java:89)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:74)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120)
at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:65)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Turn off logging

Thanks for this project. Really great stuff!!

I was wondering whether it is possible to turn off logging? I am getting all kinds of output such as INFO messages in the console.

Thanks in advance

Add optional argument to function mockk to configure created mock

Now we have a lot of cases when we create mock and want to configure it on the place (usually set every for methods).
To do that now we use apply:

val someMock: SomeClass = mockk().apply {
    every { someMethod() } returns "Foo"
}

Would be helpful to have mock configuration lambda with receiver as the latest argument in mockk:
Now

inline fun <reified T : Any> mockk(
    name: String? = null,
    relaxed: Boolean = false,
    vararg moreInterfaces: KClass<*>
): T

After:

inline fun <reified T : Any> mockk(
        name: String? = null,
        relaxed: Boolean = false,
        vararg moreInterfaces: KClass<*>,
        block: T.() -> Unit = {} // Cannot be null, but we can reuse cached instance to avoid calling empty block
): T

so now you can use mockk this way:

val someMock: SomeClass = mockk {
    every { someMethod() } returns "Foo"
}

Also works with all other optional arguments

Bug: Mocking varargs

In Mockito there is anyVararg() but mockk does not have this.
Consider the following example:

interface Foo {
   fun foo(vararg args: String, otherArg: String)
   fun foo(args: List<String>, otherArg: String)
}

@Test
fun varargTest() {
   val mock = mockk<Foo>()
   // this works as expected, matching the List<String> version
   every { mock.foo(args = any<List<String>>(), otherArg = any()) } just Runs

   // this does not work, compiles but fails at runtime with:
   // io.mockk.MockKException: Failed matching mocking signature for
   // Foo(#1).foo([529c407ddf5619f7], -4522a650db14c274)
   // left matchers: [any()]
   every { mock.foo(args = *arrayOf(any()), otherArg = any()) } just Runs
}

Is there another way to mock the vararg version of foo?

java.lang.AssertionError: Verification failed: call 2 of 2

My code is as follows:

[some init code...]
every { myMockedHelper.getSomething(FLAG, "Some string", mockContext, somePath) } returns mockAsyncTask
every { myMockedHelper.executeAsyncTaskParallel(mockAsyncTask) } just Runs

MyConnector.getHelperGraph().getOtherHelper().showStuffOnUi(FLAG, "Some string", mockContext)
verify { MyConnector.getHelperGraph().getOtherHelper().showStuffOnUi(FLAG, "Some string", mockContext)

When running the test, it fails with the following error.

java.lang.AssertionError: Verification failed: call 2 of 2: MyHelper(#2).executeAsyncTaskParallel(eq(AsyncTask(child of #2)))). Only one matching call to MyHelper(#2)/executeAsyncTaskParallel(AsyncTask) happened, but arguments are not matching:
[0]: argument: AsyncTask(#3), matcher: eq(AsyncTask(child of #2)), result: -

How can I solve this issue? What is causing this?

Fix typos

dsl/common/src/main/kotlin/io/mockk/Matchers.kt comparision -> comparison
agent/src/main/java/io/mockk/proxy/MockKInstrumentation.java tranform -> transform

Verify failing with arguments not matching

Relevant StackOverflow

I've noticed that sometimes verify fails with "... call to ... happened, but arguments are not matching"

Here is a sample test that shows verify failing:

class TestStuff {

    val stuff = "1"

    @RelaxedMockK
    lateinit var testService: TestService

    @RelaxedMockK
    lateinit var testInterface: TestInterface

    @Before
    fun setup() {
        MockKAnnotations.init(this)

        every { testInterface.testStuff } returns stuff
    }

    @Test
    fun testStuffCalled() {
        testService.testStuff(testInterface.testStuff)

        verify { testService.testStuff(testInterface.testStuff) }
    }
}

interface TestInterface {
    val testStuff: String
}

class TestService {

    fun testStuff(stuff: String) {
    }
}

Unable to mock Enum responses

I'm having some trouble mocking enum responses, for example, if i have the following ugly kotlin class.
Using Kotlin 1.2.20 and mockk 1.7

class KotlinClassWithEnumMember {
    var type: EnumType? = null

    enum class EnumType {
        ONE, TWO, THREE
    }
}

And the following test code

@Test
fun `Test mocking enum member in class`() {
    val mockedClass = mockk<ClassWithEnumMember>()
    every { mockedClass.type } returns ClassWithEnumMember.EnumType.ONE
    assertEquals(ClassWithEnumMember.EnumType.ONE, mockedClass.type, "Enum returned does not match mocked response")
}

It will throw the following error:


kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Reflection on built-in Kotlin types is not yet fully supported. No metadata found for public final val name: kotlin.String defined in kotlin.Enum[DeserializedPropertyDescriptor@31aa3ca5]

	at kotlin.reflect.jvm.internal.RuntimeTypeMapper.mapPropertySignature(RuntimeTypeMapper.kt:212)
	at kotlin.reflect.jvm.internal.KPropertyImpl.<init>(KPropertyImpl.kt:49)
	at kotlin.reflect.jvm.internal.KProperty1Impl.<init>(KProperty1Impl.kt:27)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.createProperty(KDeclarationContainerImpl.kt:91)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.access$createProperty(KDeclarationContainerImpl.kt:31)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$visitor$1.visitPropertyDescriptor(KDeclarationContainerImpl.kt:53)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl$getMembers$visitor$1.visitPropertyDescriptor(KDeclarationContainerImpl.kt:51)
	at kotlin.reflect.jvm.internal.impl.descriptors.impl.PropertyDescriptorImpl.accept(PropertyDescriptorImpl.java:467)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:66)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:152)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:43)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:161)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:43)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:167)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:43)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl.getMembers(KClassImpl.kt:182)
	at kotlin.reflect.full.KClasses.getFunctions(KClasses.kt:90)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:137)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper.varArgPosition(JvmMockFactoryHelper.kt:53)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper.toDescription(JvmMockFactoryHelper.kt:69)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:16)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:12)
	at io.mockk.impl.instantiation.JvmMockFactoryKt$sam$MockKInvocationHandler$4dff1f07.invocation(JvmMockFactory.kt)
	at io.mockk.proxy.MockKCallProxy.call(MockKCallProxy.java:24)
	at java.lang.Enum.hashCode(Enum.java:152)
	at io.mockk.RecordedCall.hashCode(API.kt)
	at java.util.HashMap.hash(HashMap.java:339)
	at java.util.HashMap.put(HashMap.java:612)
	at io.mockk.impl.recording.PermanentMocker.describeCallTree(PermanentMocker.kt:98)
	at io.mockk.impl.recording.PermanentMocker.access$describeCallTree(PermanentMocker.kt:11)
	at io.mockk.impl.recording.PermanentMocker$mock$callTree$1.invoke(PermanentMocker.kt:28)
	at io.mockk.impl.recording.PermanentMocker$mock$callTree$1.invoke(PermanentMocker.kt:11)
	at io.mockk.impl.recording.CommonCallRecorder.safeExec(CommonCallRecorder.kt:66)
	at io.mockk.impl.log.SafeLog.exec(SafeLog.kt:10)
	at io.mockk.impl.recording.PermanentMocker.mock(PermanentMocker.kt:28)
	at io.mockk.impl.recording.states.RecordingState.mockPermanently(RecordingState.kt:85)
	at io.mockk.impl.recording.states.RecordingState.round(RecordingState.kt:30)
	at io.mockk.impl.recording.CommonCallRecorder.round(CommonCallRecorder.kt:45)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:47)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:25)
	at KotlinClassWithEnumMemberTest.Test mocking enum member in lateinit class(KotlinClassWithEnumMemberTest.kt:63)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Furthermore, any other every calls on the same class (different mock instance and different field) will throw a


io.mockk.MockKException: Bad recording sequence. State: StubbingState

	at io.mockk.impl.recording.states.CallRecordingState.cancelAndThrowBadRecordingState(CallRecordingState.kt:30)
	at io.mockk.impl.recording.states.CallRecordingState.startStubbing(CallRecordingState.kt:13)
	at io.mockk.impl.recording.CommonCallRecorder.startStubbing(CommonCallRecorder.kt:32)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:20)
	at KotlinClassWithEnumMemberTest.Test mocking string member in lateinit class(KotlinClassWithEnumMemberTest.kt:69)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

There is a project with the minimal unittests set up over here: https://github.com/sleepkever/mockk-enumtest

Is there something i'm doing wrong here?

Recieve Instantiation Error on Argument-Matching Arrays

I could not see in the documentation which I find straightforward any mention of not supporting Array argument matching.

With that in mind could I asking whether this is a Mockk bug, or what is being done wrong in this code.

Stacktrac

java.lang.InstantiationError: [Lorg.springframework.jdbc.core.namedparam.SqlParameterSource;
	at sun.reflect.GeneratedSerializationConstructorAccessor19.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at io.mockk.shadowed.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
	at io.mockk.proxy.MockKProxyMaker.newEmptyInstance(MockKProxyMaker.java:184)
	at io.mockk.proxy.MockKProxyMaker.instance(MockKProxyMaker.java:52)
	at io.mockk.impl.InstantiatorImpl.instantiate(Instantiator.kt:53)
	at io.mockk.impl.InstantiatorImpl.signatureValue(Instantiator.kt:109)
	at io.mockk.impl.CallRecorderImpl.matcher(CallRecording.kt:97)

What I am trying to mock:
org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(String, Array<SqlParameterSource>)

How I am trying to mock it:

        every {
            localDb.batchUpdate(
                match{ sql: String ->
                    sql == PaymentDao.Companion.PAYMENT_INSERT_SQL_STMT
                },
                any<Array<SqlParameterSource>>()
            )
         } returns intArrayOf(1)

equivalent of verifyNoMoreInteractions() ?

Hi all, I'm converting many tests in Kotlin + Mockk and I wonder how to run the equivalent of verifyNoMoreInteractions() from Mockito?

I can do verifyZeroInteractions() with verify(exactly=0) { .. } but for the other one I don't see a way.

Any help ;) ?

Class cast exception while mocking MutableList

Hello,

I'm having problems to mock a mutable list.

My use case is that I simple want a mock for a mutableList and specify what list to return in the mutableList.toList() call. But when I try to assert the result, I get a class cast exception:

java.lang.ClassCastException: java.util.Collections$SingletonList cannot be cast to java.lang.Integer

Here a simple code that shows the problem:

class Test () {

    val mutableList = mockk<MutableList<String>>()

    @Test
    fun test() {

        val expectedList = listOf("1")
        every { mutableList.toList() } returns expectedList

        val list = mutableList.toList()
        Assert.assertEquals(expectedList, list)

    }
}

lateinit property has not been initialized

I have this code:

interface IFoo

class Foo:IFoo {
	fun method(){
		// ...
	}
}

abstract class AbstractBar<T:IFoo>{
    @Inject
    lateinit var foo: T
}



class Bar: AbstractBar<Foo>() {
    fun call(){
        foo.method()
    }
}

class Test {
    @MockK
    lateinit var foo: Foo

    @InjectMockKs lateinit var bar: Bar

    @Before
    fun setUp() = MockKAnnotations.init(this)


    @Test
    fun test() {
        every { foo.method() } answers { nothing }
        bar.call()
        verify { foo.method() }
    }
}

and it produces an error:
kotlin.UninitializedPropertyAccessException: lateinit property foo has not been initialized

mockk version: 1.7.12

What do I need to do to get it right? or is it a bug?

Is there a way to mock a property value?

When I use the following code to mock a property value, I get nulls.

    private val view = mockk<LoginView>(relaxed = true)
    private val auth = mockk<AuthenticationManager>(relaxed = true)
    private val presenter = LoginPresenter(auth)

    @Test
    fun onSignInClicked_loginInvalid_showError(){
        every { view.login } returns "dd"
        every { view.password } returns "password"

        presenter.onSignInClicked()
...

Is there a workaround for this problem or am I missing something?

List verification failure

In the last line it will fail, but it shouldn't, as much I understand:

@Test fun list() {
        val f: (List<Int>) -> Unit = mockk {
            every { [email protected](any()) } just Runs
        }
        val list = listOf(1, 2, 3, 4, 5)
        val listClone = list.toList()
        f(list)
        Assert.assertEquals(list, listClone)
        verify { f(listClone) }
}

Bug: mocking java static method exception - o.mockk.MockKException: No other calls allowed in stdObjectAnswer than equals/hashCode/toString

sample

running that code leads to MockKException:

objc[29348]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/bin/java (0x1042c24c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10434e4e0). One of the two will be used. Which one is undefined.
2018-03-21 12:17:18 DEBUG - [AbstractMockFactory] Creating spyk for MyLog4jExecutor name=#1, moreInterfaces=[]
2018-03-21 12:17:18 DEBUG - [AbstractMockFactory] Creating mockk for Thread name=#2, moreInterfaces=[]
2018-03-21 12:17:19 DEBUG - [AbstractMockFactory] Creating mockk for Runnable name=#3, moreInterfaces=[]
2018-03-21 12:17:19 DEBUG - [JvmStaticMockFactory] Creating static mockk for ThreadContext
2018-03-21 12:17:19 DEBUG - [MockKProxyMaker] Injecting handler to class org.apache.logging.log4j.ThreadContext for static methods

io.mockk.MockKException: No other calls allowed in stdObjectAnswer than equals/hashCode/toString

at io.mockk.impl.stub.MockKStub.stdObjectAnswer(MockKStub.kt:78)

part of my dependencies:
dependencies

Formatting: [Feature request] Better error report format

So, for a error report like this

Verification failed: call 2 of 2: class nz.salect.kotlinidiom.http.HttpKt.post(eq(http://localhost:8080/Login), eq({devid=, password=iAmNotAPassword!}), null())). Only one matching call to HttpKt(static HttpKt)/post(String, Map, Map) happened, but arguments are not matching:
[0]: argument: http://localhost:8080/Login, matcher: eq(http://localhost:8080/Login), result: +
[1]: argument: {devid=fake-dev-id, password=iAmNotAPassword!}, matcher: eq({devid=, password=iAmNotAPassword!}), result: -
[2]: argument: null, matcher: null(), result: +

Stack trace:
                                                       nz.salect.kotlinidiom.http.HttpKt.post              (http.kt:57)                               
                                                  nz.salect.kmoblib.services.AuthService.login             (AuthService.kt:40)                        
                                       nz.salect.kmoblib.AuthServiceTest$login_success$1.invoke            (AuthServiceTest.kt:165)                   
                                       nz.salect.kmoblib.AuthServiceTest$login_success$1.invoke            (AuthServiceTest.kt:17)                    
                                                       nz.salect.kmoblib.AuthServiceTest.mockHttpPost      (AuthServiceTest.kt:253)                   
                                                       nz.salect.kmoblib.AuthServiceTest.login_success     (AuthServiceTest.kt:164)                   
                                                    sun.reflect.NativeMethodAccessorImpl.invoke0           (NativeMethodAccessorImpl.java:-2)N        
                                                    sun.reflect.NativeMethodAccessorImpl.invoke            (NativeMethodAccessorImpl.java:62)         
                                                sun.reflect.DelegatingMethodAccessorImpl.invoke            (DelegatingMethodAccessorImpl.java:43)     
                                                                java.lang.reflect.Method.invoke            (Method.java:498)                          
                                               org.junit.runners.model.FrameworkMethod$1.runReflectiveCall (FrameworkMethod.java:50)                  
                                     org.junit.internal.runners.model.ReflectiveCallable.run               (ReflectiveCallable.java:12)      

It's detailed but still one more problem:

  1. Some lines are too long such that you need horizontal scroll in order to inspect them all.

I think we can't avoid horizontal scroll in every cases, but still I think mockk can deliever a better report like this:

Verification failed: call 2 of 2: 

class nz.salect.kotlinidiom.http.HttpKt.post(). 

Only one matching call to HttpKt(static HttpKt)/post(String, Map, Map) happened, but arguments are not matching:

[0]: 2nd argument mismatch: 
    expect: {devid=fake-dev-id, password=iAmNotAPassword!}, 
    actual: {devid=, password=iAmNotAPassword!}
    
Stack trace:
nz.salect.kotlinidiom.http.HttpKt.post                      (http.kt:57)                               
nz.salect.kmoblib.services.AuthService.login                (AuthService.kt:40)                        
nz.salect.kmoblib.AuthServiceTest$login_success$1.invoke    (AuthServiceTest.kt:165)                   
nz.salect.kmoblib.AuthServiceTest$login_success$1.invoke    (AuthServiceTest.kt:17)                    
nz.salect.kmoblib.AuthServiceTest.mockHttpPost              (AuthServiceTest.kt:253)                   
nz.salect.kmoblib.AuthServiceTest.login_success             (AuthServiceTest.kt:164)   

Static: Mock Module wide Extension Method from Different Module

Hi,

Let's say I have an Module wide free Function in one Module:

fun getValue(): Int {
    return 1
}

With a package Path: com.company.module1
And File name FreeFunctions.kt

And I want to Mock the Response from a Test Class in another Module.
With package Path: com.company.module2

Is this possible?
I tried:

staticMockk("com.company.module1.FreeFunctions.kt").use {
    every{ getValue() } returns 1
}

But the mock is not used. Any help appreciated!

java.util.ServiceConfigurationError while mocking classes instance methods for Kotlin 1.2.21

Hello,

I am reproducing the following error when I am trying to mock the android.database.Cursor.

java.util.ServiceConfigurationError: kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition: Provider kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition could not be instantiated
class SomeTest {
    val c = mockk<Cursor>()

    @Test
    fun name() {
        every { c.getColumnIndex(any()) } returns 1
    }
}

Full stacktrace:

com.intellij.rt.execution.application.AppMainV2 com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 com.showmax.lib.download.downloader.SomeTesrt

java.util.ServiceConfigurationError: kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition: Provider kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition could not be instantiated

	at java.util.ServiceLoader.fail(ServiceLoader.java:232)
	at java.util.ServiceLoader.access$100(ServiceLoader.java:185)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)
	at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
	at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
	at kotlin.collections.CollectionsKt___CollectionsKt.toCollection(_Collections.kt:1042)
	at kotlin.collections.CollectionsKt___CollectionsKt.toMutableList(_Collections.kt:1075)
	at kotlin.collections.CollectionsKt___CollectionsKt.toList(_Collections.kt:1066)
	at kotlin.reflect.jvm.internal.impl.resolve.OverridingUtil.<clinit>(OverridingUtil.java:45)
	at kotlin.reflect.jvm.internal.impl.load.java.components.DescriptorResolverUtils.resolveOverrides(DescriptorResolverUtils.java:67)
	at kotlin.reflect.jvm.internal.impl.load.java.components.DescriptorResolverUtils.resolveOverridesForNonStaticMembers(DescriptorResolverUtils.java:45)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.addFunctionFromSupertypes(LazyJavaClassMemberScope.kt:281)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.computeNonDeclaredFunctions(LazyJavaClassMemberScope.kt:245)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:89)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:51)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:402)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:470)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.getContributedFunctions(LazyJavaScope.kt:224)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getContributedFunctions(LazyJavaClassMemberScope.kt:654)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getFunctionsFromSupertypes(LazyJavaClassMemberScope.kt:370)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.computeNonDeclaredFunctions(LazyJavaClassMemberScope.kt:241)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:89)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:51)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:402)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:470)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.getContributedFunctions(LazyJavaScope.kt:224)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getContributedFunctions(LazyJavaClassMemberScope.kt:654)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.computeDescriptors(LazyJavaScope.kt:326)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$allDescriptors$1.invoke(LazyJavaScope.kt:57)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$allDescriptors$1.invoke(LazyJavaScope.kt:51)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:323)
	at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedNotNullLazyValue.invoke(LockBasedStorageManager.java:364)
	at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.getContributedDescriptors(LazyJavaScope.kt:305)
	at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(ResolutionScope.kt:37)
	at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:61)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:139)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$declaredNonStaticMembers$2.invoke(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclaredNonStaticMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:148)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticMembers$2.invoke(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:154)
	at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:39)
	at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:93)
	at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:32)
	at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllMembers(KClassImpl.kt)
	at kotlin.reflect.jvm.internal.KClassImpl.getMembers(KClassImpl.kt:169)
	at kotlin.reflect.full.KClasses.getFunctions(KClasses.kt:90)
	at kotlin.reflect.jvm.ReflectJvmMapping.getKotlinFunction(ReflectJvmMapping.kt:137)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper.varArgPosition(JvmMockFactoryHelper.kt:53)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper.toDescription(JvmMockFactoryHelper.kt:69)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:16)
	at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invoke(JvmMockFactoryHelper.kt:12)
	at io.mockk.impl.instantiation.JvmMockFactoryKt$sam$MockKInvocationHandler$4dff1f07.invocation(JvmMockFactory.kt)
	at io.mockk.proxy.MockKProxyInterceptor.intercept(MockKProxyInterceptor.java:20)
	at android.database.Cursor$ByteBuddy$p9JdW6Uq$ByteBuddy$kCWr7SV9.getColumnIndex(Unknown Source)
	at com.showmax.lib.download.downloader.SomeTesrt$name$1.invoke(SomeTesrt.kt:22)
	at com.showmax.lib.download.downloader.SomeTesrt$name$1.invoke(SomeTesrt.kt:17)
	at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:22)
	at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:31)
	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:25)
	at com.showmax.lib.download.downloader.SomeTesrt.name(SomeTesrt.kt:29)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:488)
	at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:209)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:109)
	at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:36)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:63)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.InstantiationException: kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition
	at java.lang.Class.newInstance(Class.java:427)
	at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
	... 93 more
Caused by: java.lang.NoSuchMethodException: kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.newInstance(Class.java:412)
	... 94 more


Process finished with exit code 255

Bug: StackOverflowError using spyk but not spying with mockito in Robolectric

Hi! First things first, thanks for the great work done.

I have a test which looks like this and it's working properly:

val activity = Robolectric.buildActivity(MainActivity::class.java).get()
val testActivity = Mockito.spy(activity)

testActivity.onCreate(null)

Mockito.verify(testActivity).setContentView(R.layout.activity_main)

How could I achieve the same with Mockk?

I have tried the following but I`m getting a StackOverflowError:

val activity = Robolectric.buildActivity(MainActivity::class.java).get()
val testActivity = spyk(activity)

testActivity.onCreate(null)

verify { testActivity.setContentView(R.layout.activity_main) }

Here the full stack trace (mockk version: 1.7.10):
https://gist.github.com/PublioDev/53c372a8fe69989a9b8f36b9b380c733

Bug: Mocking kotlin objects which has variables initialization

Ex:

      object Real {
        var filePath = getExternalStorage("dir").path
      }

Now when trying to mock this using, objectMockk(Real).mock(), I get,

       java.lang.ExceptionInInitializerError,
      Caused by: java.lang.IllegalStateException: getExternalStorage("dir") must not be null

for trying to access external storage. Is there any way to mock these kind of objects?

Feature: Support Kotlin/Native in MockK

For multiplatform projects it would be really nice if MockK would support Kotlin/Native as well. If some missing functionality on K/N side is needed, please let us know, and we will add it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.