mocking library for Kotlin

Last update: Aug 12, 2022

mockk kotlin

Gitter Relase Version Change log codecov Android Matrix tests Open Source Helpers

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.

Spring support

Kotlin version support

From version 1.10.0 MockK does not support Kotlin 1.2.*

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

Table of contents:

  • auto-gen TOC: {:toc}

Examples, guides & articles

Japanese guides and articles

Chinese guides and articles

Installation

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

Gradle/maven dependency

Approach Instruction
Gradle    
testImplementation "io.mockk:mockk:{version}"
Gradle (Kotlin DSL)    
testImplementation("io.mockk:mockk:{version}")
Maven
<dependency>
    <groupId>io.mockk</groupId>
    <artifactId>mockk</artifactId>
    <version>{version}</version>
    <scope>test</scope>
</dependency>
android Unit    
testImplementation "io.mockk:mockk:{version}"
android Instrumented    
androidTestImplementation "io.mockk:mockk-android:{version}"
Common multiplatform    
testImplementation "io.mockk:mockk-common:{version}"

where {version} corresponds to version as below:

  • Kotlin 1.3+ and Coroutines 1.0+ Version: Download
  • Kotlin 1.2 Compatible Version: Download

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)

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 is injecting 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 somehow initialized. 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.

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
}

Spy

Spies allow to mix mocks and real objects.

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

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

verify { car.drive(Direction.NORTH) }

confirmVerified(car)

Note: the spy object is a copy of a passed object.

Relaxed mock

A relaxed mock is the mock that returns some simple value for all functions. This allows to skip specifying behavior for each case, while still allowing to stub 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 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()

Mock relaxed for functions returning Unit

In case you would like 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<MockCls>(relaxUnitFun = true)

Annotation:

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

MockKAnnotations.init:

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

Object mocks

Objects can be transformed to mocks in the following way:

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

mockkObject(MockObj) // applies mocking to an Object

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

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

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

To revert back, use unmockkAll or unmockkObject:

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

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

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

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

val newObjectMock = mockk<MockObj>()

Class mock

Sometimes you need a mock of 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, they 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 taking a String
} returns 3
every {
    constructedWith<MockCls>(EqMatcher(4)).add(any()) // Mocks the constructor taking 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: in case 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:

val car = mockk<Car>()

val slot = slot<Double>()
val list = mutableListOf<Double>()

every {
  car.recordTelemetry(
    speed = capture(slot), // makes mock match call 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`
  )
} answers {
  println(slot.captured)

  Outcome.RECORDED
}


every {
  car.recordTelemetry(
    speed = capture(list),
    direction = Direction.SOUTH
  )
} answers {
  println(list)

  Outcome.RECORDED
}

car.recordTelemetry(speed = 15, direction = Direction.NORTH) // prints 15
car.recordTelemetry(speed = 16, direction = Direction.SOUTH) // prints 16

verify(exactly = 2) { car.recordTelemetry(speed = or(15, 16), direction = any()) }

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)

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 does not 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 in case there are some calls left without verification.

Some calls may be skipped from such 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

Recording exclusions

To exclude some not so important 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 in case 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 timeout is reached.

Returning Unit

If the function is returning 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)
}

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

  • 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) }

Extension functions

There are three cases of extension function:

  • class wide
  • object wide
  • module wide

In case of 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 as argument the module's class name. 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()
}

On 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 File.endsWith() extension function 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

In case you have a 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"]()
}

In case you want private calls to be verified, 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 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 internal state of objects associated with mock resulting in empty object
  • unmock - re-assigns transformation of classes back to original state prior to mock

Matcher extensibility

A very simple way is to create new matchers 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()
    }

Also, it is 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))

Settings file

To adjust parameters globally, there is a possibility to specify a few settings in a resource file.

How to use:

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

Where stackTracesAlignment determines whether to align the stack traces displayed when showing recorded calls 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
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 makes an object an object mock or clears it if was already transformed
unmockkObject makes an object mock back to a regular object
mockkStatic makes a static mock out of a class or clears it if it was already transformed
unmockkStatic makes a static mock back to 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 makes a constructor mock back to 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
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 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 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 is matching the matcher
varargAll(matcher) matches if all elements are matching the matcher
any...Vararg() matches any elements in vararg (specific to primitive type)
varargAny...(matcher) matches if any element is matching the matcher (specific to the primitive type)
varargAll...(matcher) matches if all elements are matching 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
throws ex specify that the matched call throws an 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)
propertyType Class specify the type of backing field accessor
nullablePropertyType Class specify the type of 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 value from the list, returning each time next element
andThenThrows ex specify that the matched call throws an 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

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 arguments of invocation
nArgs number of invocation argument
arg(n) n-th 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 casted to 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 vararg array
nArgs overall count of arguments in 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.

GitHub

https://github.com/mockk/mockk
Comments
  • 1. Feature: inline classes

    I am trying to use Kotlin's experimental inline class feature. I have an interface with a method accepting a parameter with an inline class type. In this case, every function throws an exception.

    Prerequisites

    My Kotlin version is: 1.3.0-rc-146

    • [x] I am running the latest version - 1.8.9.kotlin13
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    I should be able to define every with any() in parameters.

    Current Behavior

    Test throws an exception.

    Failure Information (for bugs)

    See the exception details in Failure logs section.

    Steps to Reproduce

    This is a test case. I am running this with Kotlin 1.3.0-rc-146, kotlin-reflect 1.3.0-rc-146, JUnit 5.1.0, mockk 1.8.9.kotlin13.

    import io.mockk.every
    import io.mockk.mockk
    import org.junit.jupiter.api.Test
    
    class MockkFailingTest {
        @Test // fails
        fun `mockk test using any()`() {
            val mocked = mockk<TestMock>(relaxed = true)
            every { mocked.test(any()) } returns 1
        }
    
        @Test // passes
        fun `mockk test using hardcoded value`() {
            val mocked = mockk<TestMock>(relaxed = true)
            every { mocked.test(MyInlineType("123")) } returns 1
        }
    
    }
    
    inline class MyInlineType(val value: String)
    
    interface TestMock {
        fun test(value: MyInlineType): Int
    }
    

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.8.9.kotlin13
    • OS: Ubuntu 18.04
    • Kotlin version: 1.3.0-rc-146
    • JDK version: 1.8
    • JUnit version: 5.1.0
    • Type of test: unit test

    Failure Logs

    io.mockk.MockKException: Failed matching mocking signature for
    SignedCall(retValue=0, isRetValueMock=false, retType=class kotlin.Int, self=TestMock(#2), method=test-gNmuAAA(String), args=[null], invocationStr=TestMock(#2).test-gNmuAAA(null))
    left matchers: [any()]
    
    	at io.mockk.impl.recording.SignatureMatcherDetector.detect(SignatureMatcherDetector.kt:99)
    	at io.mockk.impl.recording.states.RecordingState.signMatchers(RecordingState.kt:38)
    	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 io.mockk.MockKDsl.internalEvery(API.kt:93)
    	at io.mockk.MockKKt.every(MockK.kt:104)
    	at conduit.handler.LoginHandlerImplTest.mockk test(LoginHandlerImplTest.kt:79)
    	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.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436)
    	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170)
    	at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58)
    	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112)
    	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$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:74)
    	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)
    
    Reviewed by alisabzevari at 2018-10-06 11:25
  • 2. Bug: MockKAgentException when creating a mock on >= Api level 28 due to missing 64 binaries

    Expected Behavior

    Expecting mocked instances to be initialised correctly.

    Current Behavior

    Currently, whenever a mock of a class is created a MockKAgentException is thrown (see stacktrace below) on api level 28 or greater. I don't seem to be having any issues on lower API levels.

    Steps to Reproduce

    1. Create a test case containing code to create a mock
    2. Run test

    Context

    • MockK version: 1.9.3
    • OS: >= API level 28
    • Kotlin version: 1.3.11
    • JDK version: 8
    • JUnit version: 4.12
    • Type of test: instrumented test

    Stack trace

    Caused by: io.mockk.proxy.MockKAgentException: MockK could not self-attach a jvmti agent to the current VM. This feature is required for inline mocking.
    This error occured due to an I/O error during the creation of this agent: java.io.IOException: No such file or directory
    
    Potentially, the current VM does not support the jvmti API correctly
    at io.mockk.proxy.android.AndroidMockKAgentFactory.init(AndroidMockKAgentFactory.kt:63)
    at io.mockk.impl.JvmMockKGateway.<init>(JvmMockKGateway.kt:46)
    at io.mockk.impl.JvmMockKGateway.<clinit>(JvmMockKGateway.kt:172)
    ... 33 more
    Caused by: java.io.IOException: No such file or directory
    at java.io.UnixFileSystem.createFileExclusively0(Native Method)
    at java.io.UnixFileSystem.createFileExclusively(UnixFileSystem.java:281)
    at java.io.File.createTempFile(File.java:2018)
    at java.io.File.createTempFile(File.java:2064)
    at io.mockk.proxy.android.JvmtiAgent.appendToBootstrapClassLoaderSearch(JvmtiAgent.kt:53)
    at io.mockk.proxy.android.AndroidMockKAgentFactory.init(AndroidMockKAgentFactory.kt:48)
    ... 35 more
    

    Minimal reproducible code (the gist of this issue)

    // -----------------------[ GRADLE DEFINITIONS ] -----------------------
    dependencies {
        androidTestImplementation "io.mockk:mockk-android:1.9.3"
    }
    // -----------------------[ YOUR CODE STARTS HERE ] -----------------------
    object MockHelper {
        fun mockIsEnabled(enabled: Boolean = false) {
    
            val mock: LocationChecker = mockk(relaxed = true) //failure here
    
            val component = DaggerTestAppComponent
                .builder()
                .testModule(TestModule(locationChecker = mock))
                .build()
    
            val application = Application.getApplication(InstrumentationRegistry.getTargetContext())
            application.appComponent = component
        }
    }
    
    @RunWith(AndroidJUnit4::class)
    class ScreenTest : BaseUITest() {
    
        @Before
        fun setUp() {
            MockHelper.mockIsEnabled(true)
        }
        
    }
    
    // -----------------------[ YOUR CODE ENDS HERE ] -----------------------
    
    Reviewed by jtrollkarl at 2019-05-09 13:28
  • 3. Feature: Add a way to mock a constructor with defined values

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [x] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    Actually we can mock constructors but there is no way to handle constructors parameters. Something like:

    class MockCls(val minValue: Int) {
      fun add(a: Int, b: Int) = minValue + a + b
    }
    
    mockkConstructor(MockCls::class)
    
    every { anyConstructed<MockCls>(10).add(1, 2) } returns 14
    
    assertEquals(14, MockCls(10).add(1, 2)) // note new object is created
    
    verify { anyConstructed<MockCls>(10).add(1, 2) } // success
    verify { anyConstructed<MockCls>(5).add(1, 2) } // fail
    

    For reference there is a question on SO about that.

    Reviewed by Tryle at 2018-12-29 10:24
  • 4. Discussion: what are the (near future) plans for MockK?

    This is not a MockK issue, but more a question/feedback to @oleksiyp (MockK's developer). I hope more people in the community feel this way. If so, please comment or give this issue a 👍. Or otherwise let me know what you think.

    First of all: thanks for MockK. I'm very happy with it. I hope it will continue to add value to the Kotlin community.

    Also, please note that I know you've commented on many issues already that your time is limited for good reasons. I think it's most important that you decide for yourself when to do what with your time. Please never change that.

    Now the feedback: I noticed that it's been quite quiet around MockK's developments. It's been more than half a year since the current latest release (v1.9.3) was released, while previous releases happened on about a monthly basis. In the mean time some developments have taken place: new issues and PRs were opened, addressed and closed for various things. You introduced a stale issue management bot to help you prioritise open issues. But it all went a little bit slower than before, which I understand considering that you only have 24 hours in a day to spend on whatever you decide is important. I like MockK a lot and therefore it's a pity that so little (visible) development happened since the last release. Also, the developments on the Kotlin language and official stdlib extensions, like coroutines, continue to move forward. I'm afraid MockK will lag behind at some point. And in general, I wonder what's going on with MockK and where this project is going. Therefore I want to ask you to clarify the following questions.

    What plans do you have for MockK? What do you need to keep actively developing on / maintaining MockK? Do you still want to be this project's lead developer? Do you need more time/motivation? Do you need maintainers? Do you need anything else?

    Please, see this issue as a central place where you give the MockK community feedback about what you want, what you need, or whatever ideas you have. Or maybe ask whatever questions you might have yourself.

    I'd love to help by working on MockK myself, but I think I neither have the time nor the required skills for it.

    What might be a bit of motivation is the upcoming KotlinConf: wouldn't it be awesome to have some new features/bug fixes done in time for the conference, so that it's clear that MockK is still a valuable contribution to the Kotlin community? Please let the community know what you need to make this happen. I think we all want the same? Please let the community know how we can get there.

    Reviewed by erikhuizinga at 2019-10-27 14:40
  • 5. Bug: IllegalStateException: Could not self-attach to current VM using external process on Open JDK 11.0.1

    We have main code in Java and tests in Kotlin. We build it and run the tests inside Docker container. All works locally but it does not work in our build environment. We have a Jenkins master running on AWS. It calls a slave node (also on AWS) to run the build. The build fails because of this library with the following error:

    [WARNING] Corrupted STDOUT by directly writing to native stream in forked JVM 1. See FAQ web page and the dump file /home/mbuilder/workspace/....dumpstream
    java.lang.ExceptionInInitializerError
    Caused by: java.lang.IllegalStateException: Could not self-attach to current VM using external process
    java.lang.NoClassDefFoundError: Could not initialize class io.mockk.impl.JvmMockKGateway
    

    The dumpstream file is attached 2019-02-12T15-01-39_092-jvmRun1.dumpstream(had to add .log extention for GitHub). Also, note that OurClassTest mentioned in the dumpstream is only 283 lines long, so there is no line 290 that is referenced there.

    Reviewed by Sam-Kruglov at 2019-02-13 11:43
  • 6. Bug: Newer Objenesis 2.7 introduced in 1.9.3 is failing in Android Instrumented Tests

    • [x] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Failure Information (for bugs)

    Building a test apk fails with MockK 1.9.3. No errors occur with MockK 1.9.2.

    Context

    • MockK version: 1.9.3
    • Kotlin version: 1.3.21
    • JDK version: openjdk version "1.8.0_191"
    • Type of test: android instrumented test

    This error occurs when building a test apk, not when running instrumented tests.

    Expected Behavior

    The build should be successful.

    Current Behavior

    The build fails:

    $ ./gradlew :examples:mockk:assembleAndroidTest
    D8: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
    
    > Task :examples:mockk:transformClassesWithDexBuilderForDebugAndroidTest FAILED
    com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process /home/tmura/.gradle/caches/modules-2/files-2.1/org.objenesis/objenesis/3.0.1/11cfac598df9dc48bb9ed9357ed04212694b7808/objenesis-3.0.1.jar
            at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
            at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
            at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
            at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
            at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:593)
            at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
            at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:720)
            at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:146)
            at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.transform(DexArchiveBuilderTransform.java:420)
            at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:239)
            at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:235)
            at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
            at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)
            at sun.reflect.GeneratedMethodAccessor172.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:498)
            at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
            at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50)
            at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
            at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
            at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99)
            at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
            at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
            at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
            at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
            at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
            at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
            at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
            at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
            at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
            at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
            at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
            at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
            at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:301)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:293)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:175)
            at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:91)
            at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
            at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
            at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277)
            at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
            at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
            at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
            at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: com.android.builder.dexing.DexArchiveBuilderException: Failed to process /home/tmura/.gradle/caches/modules-2/files-2.1/org.objenesis/objenesis/3.0.1/11cfac598df9dc48bb9ed9357ed04212694b7808/objenesis-3.0.1.jar
            at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.launchProcessing(DexArchiveBuilderTransform.java:909)
            at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.lambda$convertToDexArchive$6(DexArchiveBuilderTransform.java:834)
            at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
            at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
            at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
            at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
            at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
    Caused by: com.android.builder.dexing.DexArchiveBuilderException: Error while dexing.
            at com.android.builder.dexing.D8DexArchiveBuilder.getExceptionToRethrow(D8DexArchiveBuilder.java:124)
            at com.android.builder.dexing.D8DexArchiveBuilder.convert(D8DexArchiveBuilder.java:101)
            at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransform.launchProcessing(DexArchiveBuilderTransform.java:904)
            ... 6 more
    Caused by: com.android.tools.r8.CompilationFailedException: Compilation failed to complete
            at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:70)
            at com.android.tools.r8.utils.ExceptionUtils.withD8CompilationHandler(ExceptionUtils.java:43)
            at com.android.tools.r8.D8.run(D8.java:94)
            at com.android.builder.dexing.D8DexArchiveBuilder.convert(D8DexArchiveBuilder.java:99)
            ... 7 more
    Caused by: com.android.tools.r8.utils.AbortException: Error: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
            at com.android.tools.r8.utils.Reporter.failIfPendingErrors(Reporter.java:89)
            at com.android.tools.r8.utils.Reporter.fatalError(Reporter.java:60)
            at com.android.tools.r8.utils.ExceptionUtils.withCompilationHandler(ExceptionUtils.java:64)
            ... 10 more
    
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':examples:mockk:transformClassesWithDexBuilderForDebugAndroidTest'.
    > com.android.build.api.transform.TransformException: com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process /home/tmura/.gradle/caches/modules-2/files-2.1/org.objenesis/objenesis/3.0.1/11cfac598df9dc48bb9ed9357ed04212694b7808/objenesis-3.0.1.jar
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    BUILD FAILED in 14s
    47 actionable tasks: 47 executed
    

    Steps to reproduce

    1. Run git clone https://github.com/tmurakami/dexopener.git && cd dexopener
    2. Change mockk-android:1.9.2 near the end of the root build.gradle to mockk-android:1.9.3
    3. Run ./gradlew :examples:mockk:assembleAndroidTest

    The cause is that Objenesis 3.0.1 on which MockK 1.9.3 relies contains code using java.lang.invoke.MethodHandle that is not present in versions prior to Android 8.0. https://github.com/easymock/objenesis/blob/8f601c8ba1aa20bbc640e2c2bc48d55df52c489f/main/src/main/java/org/objenesis/instantiator/util/DefineClassHelper.java

    Reviewed by tmurakami at 2019-03-28 10:42
  • 7. Feature: memorizing checked calls and allow to verify no more interactions to make it similar to Mockito verifyNoMoreInteractions()

    I have read other issues related to the equivalent of Mockito's verifyNoMoreInteractions() (#6, #50) and I think there are still some use cases which current DSL does not fully cover.

    I have the following test:

    // There are interactions with mock2 before that like initialization,
    // which are not important for the test
    verifyOrder {
        mock1.firstCall()
        mock2.someCall()
        mock1.secondCall()
    }
    // There are interactions with mock1 afterwards 
    // but there are no more interactions with mock2
    

    How can I check that there were no more interactions with mock2?

    I could probably add the following:

    verifyAll {
        mock2.someCall()
    }
    

    but it doesn't work when there were calls to mock2 before someCall() (which are irrelevant for the current test, like some initialization calls etc.). Even in cases where it would work this leads to duplicate code, which quickly gets ugly when there are many calls or methods have many parameters etc.

    Would be nice if there was something like:

    verify { mock2 wasNot CalledAnymore }
    
    Reviewed by lukaszkalnik at 2018-12-26 13:19
  • 8. #152 support value classes

    Update:

    any() and slot() now support value classes!

    Summary

    • Added new 'expect' functions for 'unboxing' a value class to get its internal type, and to 'wrap' an object instance within a value class.
    • refactored RecordingState matcher to account for value classes
    • refactored the SignatureValueGenerator jvm impl to recursively generate values for value classes

    resolves #152 resolves #791 resolves #683 resolves #847

    Fix (maybe?) #778?

    Notes:

    • nested value classes aren't supported #859
    • This PR increases code duplication that should be refactored #857

    This PR will hopefully provide some support for value classes #152

    WIP - just some failing tests at the moment (credit to @qoomon)

    ~This PR is blocked at the moment because the Kotlin language level is set to 1.4 - see #850~ MockK is now on language level 1.5 🎉

    Reviewed by aSemy at 2022-07-20 19:44
  • 9. Message from Assertk assertions is not printed when using withArg block.

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [x] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    The message from AssertionFailedError (which is thrown by Assertk lib) should be printed when assertion is performed in withArg block.

    Current Behavior

    The message from AssertionFailedError (which is thrown by Assertk lib) exception is not printed when the checking is performed in withArg block.

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.11.0
    • OS: macOS Big Sur
    • Kotlin version: 1.5
    • JDK version: 11
    • JUnit version: 5
    • Type of test: unit test

    Minimal reproducible code (the gist of this issue)

    // -----------------------[ GRADLE DEFINITIONS ] -----------------------
    
    project.ext.versions = [
      junit                : '5.7.2',
      assertk           : '0.24',
      mockk            : '1.11.0'
    ]
    
    dependencies {
      testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: versions.junit
      testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: versions.junit
      testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: versions.junit
      testImplementation group: 'com.willowtreeapps.assertk', name: 'assertk-jvm', version: versions.assertk
      testImplementation group: 'io.mockk', name: 'mockk', version: versions.mockk
    }
    // -----------------------[ YOUR CODE STARTS HERE ] -----------------------
    package some.example.com
    
    import io.mockk.every
    import io.mockk.mockk
    import org.apache.kafka.common.KafkaFuture
    import kotlin.test.Test
    
    class SomeExampleTest {
    
        val orderRepository: OrderRepository = mockk()
        val orderService: OrderService = OrderService(orderRepository)
    
        @Test
        fun test() {
           // given
           thereIsOrder(anOrder())
    
          // when
          orderService.pay(anOrderPayment())
    
          // then
          wasSaved(anOrder())
        }
        
        fun wasSaved(order: Order, times: Int = 1) {
          verify(exactly = times) {
             orderRepository.save(withArg{ equalsTo(order) })
          }
        }
        
        private fun MockKAssertScope.equalsTo(order: Order) {
                assertThat(this.actual as Order)
               .hasCommandId(order.commandId)
               .hasOrderId(order.orderId)
               // and so on     
      }
    
        // walk around
        private fun MockKAssertScope.equalsToAndLog(order: Order) {
           try {
                assertThat(this.actual as Order)
               .hasCommandId(order.commandId)
               .hasOrderId(order.orderId)
               // and so on
           } catch (t: Throwable) {
               logger.error(t) {}
               throw t
           }
      }
    }
    // -----------------------[ YOUR CODE ENDS HERE ] -----------------------
    

    I found that exception is catched here, and the stacktrace is not logged.

    package io.mockk
    
    data class FunctionMatcher<in T : Any>(
        val matchingFunc: (T) -> Boolean,
        override val argumentType: KClass<*>
    ) : Matcher<T>, TypedMatcher, EquivalentMatcher {
        override fun equivalent(): Matcher<Any> = ConstantMatcher(true)
    
        override fun match(arg: T?): Boolean {
            return if(arg == null) {
                false
            } else {
                try {
                    matchingFunc(arg)
                } catch (a: AssertionError) {
                    false
                }
            }
        }
    
        override fun toString(): String = "matcher<${argumentType.simpleName}>()"
    }
    
    Reviewed by CamilYed at 2021-09-30 14:24
  • 10. Bug: MockK is not runnable together with PowerMockito

    Prerequisites

    • [x] I am running the latest version
    • [X] I checked the documentation and found no answer
    • [X] I checked to make sure that this issue has not already been filed

    Expected Behavior

    Mocking a static method

    Failure Information (for bugs)

    java.lang.ExceptionInInitializerError at my.package.ConfigUseCaseTests.getConfigs_fromJson(ConfigUseCaseTests.kt:33) 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) 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: io.mockk.MockKException: Failed to load plugin io.mockk.proxy.jvm.JvmMockKAgentFactory at io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:152) at io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:138) ... 29 more Caused by: java.lang.IllegalStateException: Error during attachment using: [email protected]c72da34 at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:377) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:351) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:319) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:305) at io.mockk.proxy.jvm.MockKInstrumentation.(MockKInstrumentation.java:57) at io.mockk.proxy.jvm.JvmMockKAgentFactory.(JvmMockKAgentFactory.java:11) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at java.lang.Class.newInstance(Class.java:442) at io.mockk.impl.JvmMockKGateway.(JvmMockKGateway.kt:150) ... 30 more Caused by: java.lang.reflect.InvocationTargetException 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 net.bytebuddy.agent.Attacher.install(Attacher.java:77) at net.bytebuddy.agent.ByteBuddyAgent.install(ByteBuddyAgent.java:372) ... 41 more Caused by: java.lang.NullPointerException at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:187) ... 47 more

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.8.0
    • OS: Mac OS High Sierra
    • Kotlin version: 1.2.30
    • JDK version: 1.8.0_161
    • Type of test: unit test

    Minimal reproducible code (the gist of this issue)

    // These are some of the Gradle implementations.
        // Power Mockito
        testImplementation 'org.powermock:powermock-api-mockito:1.6.1'
        testImplementation 'org.powermock:powermock-module-junit4-rule-agent:1.6.1'
        testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
        testImplementation 'org.powermock:powermock-module-junit4:1.6.1'
    
        // Mockk
        testImplementation "io.mockk:mockk:1.8"
    
        // Mockito
        def mockitoVersion = "1.5.0"
        testImplementation "org.mockito:mockito-core:$mockitoVersion"
        testImplementation "com.nhaarman:mockito-kotlin-kt1.1:$mockitoVersion"
        androidTestImplementation("com.nhaarman:mockito-kotlin-kt1.1:$mockitoVersion", {
            exclude group: 'org.mockito', module: 'mockito-core'
        })
        androidTestImplementation 'org.mockito:mockito-android:2.11.0'
    
        class ConfigUseCaseTests : UnitTestsResource() {
        
            private lateinit var configUseCase: ConfigUseCase
        
            @Before
            override fun setUp() {
                super.setUp()
                configUseCase = ConfigUseCase()
            }
        
            @Test
            fun getConfigs_fromJson() {
                objectMockk(SharedPreferencesHelper).mock()
                every { SharedPreferencesHelper.loadString(isA(), isA(), isA(), isA()) } returns "wooo"
                System.out.println("String:${SharedPreferencesHelper.loadString(context, "", "", null)}")
            }
        }
    
    

    I've also tested it with staticMockk or any other examples provided but I'm getting the same error.

    Reviewed by RafaRuiz at 2018-05-31 14:59
  • 11. Upgrade to Kotlin 1.4 and support the new IR backend

    Libraries that depend on Mockk and want to leverage the new IR backend offered by Kotlin 1.4 cannot do so without changes to Mockk. For example, I'd love to upgrade Doodle and Measured to the new backend to improve JS bundle size.

    The changes to Mockk include upgrading to Kotlin 1.4 and building with the new kotlin.js.compiler option set to ir, or both.

    Originally posted by @pusolito in https://github.com/mockk/mockk/issues/374#issuecomment-678993554

    Reviewed by pusolito at 2020-08-24 18:13
  • 12. any() doesn't work for kotlin.Unit

    Just be aware about usual MockK support pattern. Tickets are checked from time to time, replied, discussed, labeled, e.t.c. But real fixes are applied in a month-two month period in a bunch. If you think this is unacceptable, go on, join the project, change the world.

    Please remove sections wisely

    Below information is actually needed to make all the process of fixing faster. Choose main points. Don't blindly follow this as a set of rules. Don't waste much time. Usually, the main thing is to have a good reproducible minimal code.

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [ ] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    when I mock a funtion which has a Unit argument by every { mockObject.function(any()) }, it should return expected value.

    Current Behavior

    fail because of fail matching mocking signature

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version:1.12.0
    • OS: Windows 10
    • Kotlin version: 1.7.10
    • JDK version: 1.8
    • JUnit version: JUnit 4
    • Type of test: unit test

    Stack trace

    Failed matching mocking signature for
    SignedCall(retValue=, isRetValueMock=true, retType=class kotlin.Unit, self=MyClass(#1), method=abc(Unit), args=[kotlin.Unit], invocationStr=MyClass(#1).abc(kotlin.Unit))
    left matchers: [any()]
    io.mockk.MockKException: Failed matching mocking signature for
    SignedCall(retValue=, isRetValueMock=true, retType=class kotlin.Unit, self=MyClass(#1), method=abc(Unit), args=[kotlin.Unit], invocationStr=MyClass(#1).abc(kotlin.Unit))
    left matchers: [any()]
    	at app//io.mockk.impl.recording.SignatureMatcherDetector.detect(SignatureMatcherDetector.kt:99)
    	at app//io.mockk.impl.recording.states.RecordingState.signMatchers(RecordingState.kt:39)
    	at app//io.mockk.impl.recording.states.RecordingState.round(RecordingState.kt:31)
    	at app//io.mockk.impl.recording.CommonCallRecorder.round(CommonCallRecorder.kt:50)
    	at app//io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:63)
    	at app//io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    	at app//io.mockk.MockKDsl.internalEvery(API.kt:92)
    	at app//io.mockk.MockKKt.every(MockK.kt:98)
    	at app//cn.futu.news.maintab.optional.optionalreport.presentation.viewmodel.MyTest.testOne(MyTest.kt:17)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    	at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    	at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    	at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    	at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    	at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    	at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    	at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    	at app//org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    	at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    	at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    	at app//org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    	at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    	at app//org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    	at com.sun.proxy.$Proxy5.processTestClass(Unknown Source)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    	at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    	at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    	at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
    

    Minimal reproducible code (the gist of this issue)

    class MyTest {
    
        @Test
        fun testOne() {
            val ob = mockk<MyClass>()
           // this statement will cause Failed matching mocking signature
            every { ob.abc(any()) } answers {
                println("Mock~")
            }
    
            ob.abc(Unit)
        }
    }
    
    class MyClass {
        fun abc(a: Unit) {
            println("abc")
        }
    }
    
    Reviewed by ZeroXsLab at 2022-08-11 13:09
  • 13. Is it possible to test or capture arguments in mocked constructor?

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [x] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    Capable of mocking a constructor and capturing its arguments, or some other means to test them.

    Current Behavior

    Seems it cannot be done, or I just haven't found the correct way.

    Steps to Reproduce

    Here is a minimized example of a class that I want to test with.

    /**
     * Should be mocked in a unit test.
     */
    class AndroidData(val value: Float)
    
    /**
     * Target class to be tested.
     */
    class MyHelper() {
        fun createData(flag: Boolean): AndroidData {
            // simplified logic
            return if (flag) AndroidData(20f) else AndroidData(10f)
        }
    }
    

    I want to test that an AndroidData instance with the correct field value will be returned in each case. I tried 2 ways so these are my test cases:

    
    class LargerThan15Matcher: Matcher<Float> {
        override fun match(arg: Float?): Boolean {
            return if (arg == null) false else arg >= 15f
        }
    }
    
    class MyHelperTest : TestCase() {
        @Test
        fun testCreateData1() {
            mockkConstructor(AndroidData::class)
    
            val helper = mockk<MyHelper>(relaxed = true)
            val createdData = helper.createData(true)
    
            println("createdData=$createdData")  // AndroidData(child of #1#2)
            println("createdData.value=${createdData.value}")  // 0.0
    
            // test if the argument in AndroidData's constructor was larger than 15
            assertTrue(createdData.value >= 15f)  // assertion failed
        }
    
        @Test
        fun testCreateData2() {
            mockkConstructor(AndroidData::class)
            // Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
            every {
                constructedWith<AndroidData>(LargerThan15Matcher())
            }
    
            val helper = mockk<MyHelper>(relaxed = true)
            val createdData = helper.createData(true)
    
            println("createdData=$createdData")  // AndroidData(child of #1#2)
            println("createdData.value=${createdData.value}")  // 0.0
    
            // test if the argument in AndroidData's constructor was larger than 15
            assertTrue(createdData.value >= 15f)
        }
    }
    

    Please be noted that the AndroidData would simulate an Android class that would be stubbed in a unit test. That is, I have to mock that class in a unit test, right?

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.12.5
    • OS: Ubuntu 18.04 LTS
    • Kotlin version: 1.6.0
    • JDK version: 1.8
    • JUnit version: JUnit 4
    • Type of test: unit test

    Stack trace

    The second test case (testCreateData2) would produce this

    Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
    io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
    	at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
    	at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
    	at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
    	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:64)
    	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    	at io.mockk.MockKDsl.internalEvery(API.kt:93)
    	at io.mockk.MockKKt.every(MockK.kt:98)
    	at com.omnieyes.eventproducer.sid.util.iot.MyHelperTest.testCreateData2(MyHelperTest.kt:50)
    	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 junit.framework.TestCase.runTest(TestCase.java:177)
    	at junit.framework.TestCase.runBare(TestCase.java:142)
    	at junit.framework.TestResult$1.protect(TestResult.java:122)
    	at junit.framework.TestResult.runProtected(TestResult.java:142)
    	at junit.framework.TestResult.run(TestResult.java:125)
    	at junit.framework.TestCase.run(TestCase.java:130)
    	at junit.framework.TestSuite.runTest(TestSuite.java:241)
    	at junit.framework.TestSuite.run(TestSuite.java:236)
    	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:90)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    	at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    	at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    	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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    	at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    	at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
    	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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
    	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
    	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
    	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    	at java.lang.Thread.run(Thread.java:750)
    

    Minimal reproducible code (the gist of this issue)

    just right-click on the test file and press Run 'MyHelperTest.kt'

    package com.omnieyes.eventproducer.sid.util.iot
    
    import io.mockk.Matcher
    import io.mockk.every
    import io.mockk.mockk
    import io.mockk.mockkConstructor
    import junit.framework.TestCase
    import org.junit.Test
    
    /**
     * Should be mocked in a unit test.
     */
    class AndroidData(val value: Float)
    
    /**
     * Target class to be tested.
     */
    class MyHelper() {
        fun createData(flag: Boolean): AndroidData {
            // simplified logic
            return if (flag) AndroidData(20f) else AndroidData(10f)
        }
    }
    
    class LargerThan15Matcher: Matcher<Float> {
        override fun match(arg: Float?): Boolean {
            return if (arg == null) false else arg >= 15f
        }
    }
    
    class MyHelperTest : TestCase() {
        @Test
        fun testCreateData1() {
            mockkConstructor(AndroidData::class)
    
            val helper = mockk<MyHelper>(relaxed = true)
            val createdData = helper.createData(true)
    
            println("createdData=$createdData")  // AndroidData(child of #1#2)
            println("createdData.value=${createdData.value}")  // 0.0
    
            // test if the argument in AndroidData's constructor was larger than 15
            assertTrue(createdData.value >= 15f)  // assertion failed
        }
    
        @Test
        fun testCreateData2() {
            mockkConstructor(AndroidData::class)
            // Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
            every {
                constructedWith<AndroidData>(LargerThan15Matcher())
            }
    
            val helper = mockk<MyHelper>(relaxed = true)
            val createdData = helper.createData(true)
    
            println("createdData=$createdData")  // AndroidData(child of #1#2)
            println("createdData.value=${createdData.value}")  // 0.0
    
            // test if the argument in AndroidData's constructor was larger than 15
            assertTrue(createdData.value >= 15f)
        }
    }
    
    Reviewed by joy0520 at 2022-08-11 09:55
  • 14. Bug:fail to mock anyConstructed().extensionFunc(), it execute the real code.

    Just be aware about usual MockK support pattern. Tickets are checked from time to time, replied, discussed, labeled, e.t.c. But real fixes are applied in a month-two month period in a bunch. If you think this is unacceptable, go on, join the project, change the world.

    Please remove sections wisely

    Below information is actually needed to make all the process of fixing faster. Choose main points. Don't blindly follow this as a set of rules. Don't waste much time. Usually, the main thing is to have a good reproducible minimal code.

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [ ] I am running the latest version
    • [x] I checked the documentation and found no answer
    • [x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    mock behavior with every { anyConstucted().extensionFunc() } returns xx, it should get "xx" without any real code execute.

    Current Behavior

    It executes the real code and does not reutrn "xx"

    Failure Information (for bugs)

    1. both of anyConstructed and constructedWith fail
    2. every { mockObject.extensionFunc() } works as expected
    3. eveyr { anyConstructed().notExtensionFunc() } works as expected

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.12.0
    • OS: Windows 10
    • Kotlin version: kotlin-stdlib-jdk7:1.4.32
    • JDK version: JavaVersion.VERSION_1_8
    • JUnit version: JUnit 4
    • Type of test: unit test

    Failure Logs

    ext invoke

    expected:<Mock [E]xt> but was:<Mock [Str - e]xt> Expected :Mock [E]xt Actual :Mock [Str - e]xt

    Minimal reproducible code (the gist of this issue)

    // ----------------------- Begin of  file <Test.kt> -----------------------
    package cn.sean
    
    class MyData(val str: String)
    
    fun MyData.ext(): String {
        println("ext invoke")
        return "$str - ext"
    }
    // ------------------------ end of  file <Test.kt> -------------------------
    
    // ----------------------- Begin of  file <MyDataTest.kt> -----------------------
    class MyDataTest {
    
        // the assert will fail. Because we expect "Mock Ext", but it returns "Mock Str - ext"
        @Test
        fun testConstructor() {
            mockkStatic("cn.sean.TestKt")
            mockkConstructor(MyData::class)
            every { anyConstructed<MyData>().str } returns "Mock Str"
            every { anyConstructed<MyData>().ext() } returns "Mock Ext"
            val myData = MyData("abc")
    
            assertEquals("Mock Ext", myData.ext()) // will print "ext invoke" and return "abc - ext", which is not run as mocked
        }
    
        // This assert will pass
        @Test
        fun testMockObject() {
            mockkStatic("cn.sean.TestKt")
            val myData = spyk(MyData("abc"))
            every { myData.str } returns "Mock Str"
            every { myData.ext() } returns "Mock Ext"
    
            assertEquals("Mock Ext", myData.ext()) // for spyk object, extension function works as expected
        }
    
    }
    // ------------------------ end of  file <Test.kt> -------------------------
    
    Reviewed by ZeroXsLab at 2022-08-02 03:56
  • 15. Mockk produces incorrect bytecode when running with coverage

    Mockk fails to transform bytecode after Kover. Original issue in Kover

    Minimal reproducible code

    Please see MockkReproducer.zip In build.gradle.kts file, the Kover plugin is enabled, so all the tests are running with coverage.

    Failure Information (for bugs)

    In Kover we have investigated the issue: we have analysed the bytecode of the problem class okhttp3.Response on the different stages of instrumentation. Please see the data folder in the attached project. The class files inside this folder were gained by stopping the program via debugger at this line: InliningClassTransformer.kt#L91 Here we have printed classfileBuffer content to before_mockk/Responce.class, and type.bytes to after_mockk/Responce.class with coverage enabled (in coverage subfolder) and coverage disabled (in no_coverage subfolder, please comment Kover pluggin in build.gradle.kts to disable coverage) Then we have decompiled the class files to bytecode.txt file in each of the cases via javap -c -l -v Response.class command.

    Expected Behavior

    Mockk runs successfully with Kover plugin enabled

    Current Behavior

    Classfile produced by mockk data/coverage/after_mockk/Responce.class fails the verification, while the classfile on all the other stages is correct.

    The return statement after kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List; method call is transformed into a single goto instruction, so the stack map is incorrect, as the okhttp3/Headers element in unexpected on the stack. It is correct to replace return with astore, pop, aload, goto sequence

    Steps to Reproduce

    1. run :test --tests "MockkCoverageTest.testMockingResponse" task in the attached project
    2. you will get a VerifyError

    Alternatively,

    1. Running the InliningClassTransformer#transform method with the contents of coverage/before_mockk/Responce.class (which contains correct bytecode) as a classfileBuffer parameter leads to the incorrect bytecode in the output, which can be found in the coverage/after_mockk/Responce.class file

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.12.5
    • OS: macOS 12.4
    • Kotlin version: 1.7.10
    • JDK version: 11
    • JUnit version: 5.6
    • Type of test: unit test

    Stack trace

    java.lang.VerifyError
    	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses0(Native Method)
    	at java.instrument/sun.instrument.InstrumentationImpl.retransformClasses(InstrumentationImpl.java:167)
    	at io.mockk.proxy.jvm.transformation.JvmInlineInstrumentation.retransform(JvmInlineInstrumentation.kt:28)
    	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1.invoke(RetransformInlineInstrumentation.kt:19)
    	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation$execute$1.invoke(RetransformInlineInstrumentation.kt:16)
    	at io.mockk.proxy.common.transformation.ClassTransformationSpecMap.applyTransformation(ClassTransformationSpecMap.kt:41)
    	at io.mockk.proxy.common.transformation.RetransformInlineInstrumentation.execute(RetransformInlineInstrumentation.kt:16)
    	at io.mockk.proxy.jvm.ProxyMaker.inline(ProxyMaker.kt:88)
    	at io.mockk.proxy.jvm.ProxyMaker.proxy(ProxyMaker.kt:30)
    	at io.mockk.impl.instantiation.JvmMockFactory.newProxy(JvmMockFactory.kt:34)
    	at io.mockk.impl.instantiation.AbstractMockFactory.newProxy$default(AbstractMockFactory.kt:24)
    	at io.mockk.impl.instantiation.AbstractMockFactory.mockk(AbstractMockFactory.kt:59)
    	at MockkCoverageTest.testMockingResponse(MockkCoverageTest.kt:24)
    

    Verification error when running java okhttp3.Response in the data/coverage/after_mockk directory

    Error: Unable to initialize main class okhttp3.Response
    Caused by: java.lang.VerifyError: Inconsistent stackmap frames at branch target 296
    Exception Details:
      Location:
        okhttp3/Response.challenges()Ljava/util/List; @269: goto
      Reason:
        Current frame's stack size doesn't match stackmap.
      Current Frame:
        bci: @269
        flags: { }
        locals: { 'okhttp3/Response', 'java/util/concurrent/Callable', 'okhttp3/Response', '[I' }
        stack: { 'okhttp3/Headers', 'java/util/List' }
      Stackmap Frame:
        bci: @296
        flags: { }
        locals: { 'okhttp3/Response', 'java/util/concurrent/Callable' }
        stack: { 'java/util/List' }
      Bytecode:
        0000000: 2ab6 015a 1301 5ca6 0035 03bd 0004 be04
        0000010: a000 1303 bd00 0403 3213 015c a600 0701
        0000020: a700 4c03 bd00 04be 05a0 0013 03bd 0004
        0000030: 0432 1301 5ca6 0007 01a7 0033 1401 5d2a
        0000040: b801 634c 2bc6 000b 2b2a b601 679a 0007
        0000050: 01a7 001b 2b2a 1202 1301 a203 bd01 6ab6
        0000060: 016e 03bd 0004 b601 72a7 0003 4c2b c600
        0000070: 0701 a700 b62a 4d00 b200 6ac7 000b 126c
        0000080: b800 72b3 006a b200 6a4e 2d11 002b 5c2e
        0000090: 0460 4f2c b400 8a2d 1100 2c5c 2e04 604f
        00000a0: 2cb4 007a a700 272d 1100 2f5c 2e04 604f
        00000b0: a700 342d 1100 2e5c 2e04 604f a700 362d
        00000c0: 1100 2d5c 2e04 604f a700 39ab ffff fff4
        00000d0: 0000 0002 0000 0191 ffff ffdc 0000 0197
        00000e0: ffff ffe8 2d11 0030 5c2e 0460 4f12 ffa7
        00000f0: 0021 2d11 0031 5c2e 0460 4f13 0101 a700
        0000100: 122d 1100 325c 2e04 604f b801 06a7 001b
        0000110: 2d11 002c 5c2e 0460 4f2d 1100 2b5c 2e04
        0000120: 604f b801 0ca7 0003 4d2b c600 0d2b b901
        0000130: 7801 00c0 018d 4da7 0003 2cb0          
      Stackmap Table:
        same_frame(@35)
        same_frame(@60)
        append_frame(@80,Object[#352])
        same_frame(@84)
        full_frame(@108,{Object[#2]},{Object[#372]})
        append_frame(@117,Object[#372])
        append_frame(@119,Object[#2])
        same_frame(@134)
        full_frame(@167,{Object[#2],Object[#372],Object[#2],Object[#123]},{Object[#140]})
        same_locals_1_stack_item_frame(@179,Object[#140])
        same_locals_1_stack_item_frame(@191,Object[#140])
        full_frame(@203,{Object[#2],Object[#372],Object[#2],Object[#123]},{Object[#140],Integer})
        same_locals_1_stack_item_frame(@228,Object[#140])
        same_locals_1_stack_item_frame(@242,Object[#140])
        same_locals_1_stack_item_frame(@257,Object[#140])
        full_frame(@272,{Object[#2],Object[#372],Object[#2],Object[#123]},{Object[#140],Object[#151]})
        full_frame(@296,{Object[#2],Object[#372]},{Object[#397]})
        append_frame(@297,Object[#397])
        same_frame(@311)
        same_frame(@314)
    
    
    Reviewed by zuevmaxim at 2022-08-01 14:43
  • 16. 1.12.5 `every` fails when `kotlin.time.Duration` should be returned

    Prerequisites

    Please answer the following questions for yourself before submitting an issue.

    • [ x] I am running the latest version
    • [ x] I checked the documentation and found no answer
    • [ x] I checked to make sure that this issue has not already been filed

    Expected Behavior

    Calling the every method succeeds and returns the correct an object of kotlin.time.Duration when called

    Current Behavior

    The method calls fails and throws a java.lang.ClassCastException

    Failure Information (for bugs)

    Steps to Reproduce

    In mockk 1.12.4 I was able to use the every mocking method and return a value on a method call from a method that returns kotlin.time.Duration 1.12.5 seems to have broken this and tries to cast the kotlin.time.Duration into a java.lang.Long unsuccessfully.

    Code below.

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.12.5
    • OS: macOS X 12.4 (x86)
    • Kotlin version: 1.7.10
    • JDK version: 17
    • JUnit version: JUnit Jupiter 5.8.2
    • Type of test: unit test

    Stack trace

    /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=49646:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/Elias/.m2/repository/org/junit/platform/junit-platform-launcher/1.8.2/junit-platform-launcher-1.8.2.jar:/Users/Elias/.m2/repository/org/junit/vintage/junit-vintage-engine/5.8.2/junit-vintage-engine-5.8.2.jar:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/junit/lib/junit5-rt.jar:/Applications/IntelliJ IDEA.app/Contents/plugins/junit/lib/junit-rt.jar:/Users/Elias/Desktop/duration-mock-error/target/test-classes:/Users/Elias/Desktop/duration-mock-error/target/classes:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-test-junit/1.7.10/kotlin-test-junit-1.7.10.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-test/1.7.10/kotlin-test-1.7.10.jar:/Users/Elias/.m2/repository/junit/junit/4.13.2/junit-4.13.2.jar:/Users/Elias/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:/Users/Elias/.m2/repository/org/junit/jupiter/junit-jupiter-engine/5.8.2/junit-jupiter-engine-5.8.2.jar:/Users/Elias/.m2/repository/org/junit/platform/junit-platform-engine/1.8.2/junit-platform-engine-1.8.2.jar:/Users/Elias/.m2/repository/org/opentest4j/opentest4j/1.2.0/opentest4j-1.2.0.jar:/Users/Elias/.m2/repository/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar:/Users/Elias/.m2/repository/org/junit/jupiter/junit-jupiter-api/5.8.2/junit-jupiter-api-5.8.2.jar:/Users/Elias/.m2/repository/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.7.10/kotlin-stdlib-jdk8-1.7.10.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib/1.7.10/kotlin-stdlib-1.7.10.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-common/1.7.10/kotlin-stdlib-common-1.7.10.jar:/Users/Elias/.m2/repository/org/jetbrains/annotations/13.0/annotations-13.0.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.7.10/kotlin-stdlib-jdk7-1.7.10.jar:/Users/Elias/.m2/repository/io/mockk/mockk/1.12.5/mockk-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-common/1.12.5/mockk-common-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-dsl/1.12.5/mockk-dsl-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-dsl-jvm/1.12.5/mockk-dsl-jvm-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-agent-jvm/1.12.5/mockk-agent-jvm-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-agent-api/1.12.5/mockk-agent-api-1.12.5.jar:/Users/Elias/.m2/repository/io/mockk/mockk-agent-common/1.12.5/mockk-agent-common-1.12.5.jar:/Users/Elias/.m2/repository/org/objenesis/objenesis/3.2/objenesis-3.2.jar:/Users/Elias/.m2/repository/net/bytebuddy/byte-buddy/1.12.6/byte-buddy-1.12.6.jar:/Users/Elias/.m2/repository/net/bytebuddy/byte-buddy-agent/1.12.6/byte-buddy-agent-1.12.6.jar:/Users/Elias/.m2/repository/org/jetbrains/kotlin/kotlin-reflect/1.7.10/kotlin-reflect-1.7.10.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 ConfigTest
    Java HotSpot(TM) 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
    
    io.mockk.MockKException: Class cast exception happened.
    Probably type information was erased.
    In this case use `hint` before call to specify exact return type of a method.
    
    
    	at io.mockk.impl.InternalPlatform.prettifyRecordingException(InternalPlatform.kt:74)
    	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:66)
    	at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    	at io.mockk.MockKDsl.internalEvery(API.kt:93)
    	at io.mockk.MockKKt.every(MockK.kt:98)
    	at ConfigTest.testAnything(ConfigTest.kt:16)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    	at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    	at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    	at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    	at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    	at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    	at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
    Caused by: java.lang.ClassCastException: class kotlin.time.Duration cannot be cast to class java.lang.Long (kotlin.time.Duration is in unnamed module of loader 'app'; java.lang.Long is in module java.base of loader 'bootstrap')
    	at Config.getDurationInSeconds-UwyO8pc(Config.kt:4)
    	at ConfigTest$testAnything$1.invoke-5sfh64U(ConfigTest.kt:16)
    	at ConfigTest$testAnything$1.invoke(ConfigTest.kt:16)
    	at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
    	at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:78)
    	at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
    	at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:40)
    	... 73 more
    
    
    Process finished with exit code 255
    

    Minimal reproducible code (the gist of this issue)

    import kotlin.time.Duration.Companion.seconds
    
    class Config {
        fun getDurationInSeconds() = 0.seconds
    }
    
    import io.mockk.every
    import io.mockk.impl.annotations.MockK
    import io.mockk.junit5.MockKExtension
    import org.junit.jupiter.api.Test
    import org.junit.jupiter.api.extension.ExtendWith
    import kotlin.time.Duration
    
    @ExtendWith(MockKExtension::class)
    class ConfigTest {
    
        @MockK
        private lateinit var config: Config
    
        @Test
        fun testAnything() {
            every { config.getDurationInSeconds() } returns Duration.ZERO
        }
    }
    
    Reviewed by eliasmueller at 2022-07-28 08:01
  • 17. 1.12.5 fails to `every` certain java classes

    I created a demo/minimal project here:

    https://gitlab.com/knyttl/mockkdemo/-/tree/main

    You can see the CI build with test failure here:

    https://gitlab.com/knyttl/mockkdemo/-/jobs/2782097977

    Feel free to change the build.gradle.kts mockk version to 1.12.4 which will test correctly.

    Expected Behavior

    The tests shouldn't fail.

    Current Behavior

    The test fails with:

    kotlin.reflect.jvm.internal.KotlinReflectionInternalError: Unresolved class: class org.elasticsearch.search.sort.SortOrder$1
    

    As you can see in the CI run mentioned above.

    Failure Information (for bugs)

    See CI run mentioned above.

    Steps to Reproduce

    See the source code mentioned above. Feel free to change the version to 1.12.4 which will build correctly.

    Context

    Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

    • MockK version: 1.12.5
    • Kotlin version: 1.7.10
    • JDK version: 17

    Minimal reproducible code (the gist of this issue)

    import io.mockk.every
    import io.mockk.mockk
    import org.elasticsearch.search.sort.SortOrder
    import org.junit.jupiter.api.Test
    
    class MockkDemo {
        @Test
        fun testMockk() {
            val repo = mockk<TestClass>()
            every { repo.getSchedules() } returns "Foo"
        }
    }
    
    class TestClass {
        fun getSchedules(sortOrder: SortOrder = SortOrder.ASC): String =
            sortOrder.toString()
    }
    
    Reviewed by knyttl at 2022-07-28 07:32
Easy Response Mocking for Retrofit using annotations

Response Mocking for Retrofit using annotations. Assume Provides safe and easy way to mock API responses for retrofit-okhttp3.

Nov 16, 2021
Most popular Mocking framework for unit tests written in Java
Most popular Mocking framework for unit tests written in Java

Most popular mocking framework for Java Current version is 3.x Still on Mockito 1.x? See what's new in Mockito 2! Mockito 3 does not introduce any bre

Aug 9, 2022
A micro mocking framework for KMP

Micro-Mock A micro Kotlin/Multiplatform Kotlin Symbol Processor that generates Mocks & Fakes. Limitations: Mocking only applies to interfaces Faking o

Aug 1, 2022
A multiplatform assertion library for Kotlin

Atrium is an open-source multiplatform assertion library for Kotlin with support for JVM, JS and Android. It is designed to support multiple APIs, dif

Aug 1, 2022
Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Strikt is an assertion library for Kotlin intended for use with a test runner such as JUnit, Minutest, Spek, or KotlinTest.

Aug 18, 2022
A Kotlin Android library for heuristics evasion that prevents your code from being tested.

EvadeMe An Android library for heuristics evasion that prevents your code from being tested. User Instructions Add the maven repository to your projec

Jul 29, 2022
Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project.

Kotlin API for React Test Renderer Kotlin wrapper for React Test Renderer, which can be used to unit test React components in a Kotlin/JS project. How

Jun 8, 2022
Android library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests.
Android library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests.

Green Coffee Green Coffee is a library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests using the

Jul 21, 2022
Linkester is an Android library that aims to help Android developers test their deep links implementation.
Linkester is an Android library that aims to help Android developers test their deep links implementation.

Linkester Linkester is an Android library that aims to help Android developers test their deep links implementation. The idea is to have a new launche

Jun 26, 2022
Jitpack Library Tester

jitpack-library-test Repository for testing build from jitpack.io Red : Failed Green : Success / Pass Colaborator Very open to anyone, I'll write your

Jul 13, 2022
Turbine is a small testing library for kotlinx.coroutines Flow.

A small testing library for kotlinx.coroutines Flow

Aug 12, 2022
A library that makes it easier to write high quality automated acceptance tests

Getting started with Serenity and Cucumber Serenity BDD is a library that makes it easier to write high quality automated acceptance tests, with power

Oct 20, 2021
An experimental library for dealing with legacy code

All Super experimental! no guarantees to the public API surface. At the moment, this project is the outcome of the limitations of my search skills. Bu

Jan 18, 2022
Library to simplify and speed up the creation and work with adapters with payload.

Novalles Library to simplify and speed up the creation and work with adapters with payload. How to use Annotate your UI model with UIModel Annotation.

Jul 31, 2022
Portable validations for Kotlin

Portable validations for Kotlin ✅ Type-safe DSL ?? Multi-platform support (JVM, JS) ?? Zero dependencies Installation For multiplatform projects: kotl

Aug 11, 2022
Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing
Powerful, elegant and flexible test framework for Kotlin with additional assertions, property testing and data driven testing

Kotest is a flexible and comprehensive testing tool for Kotlin with multiplatform support. To learn more about Kotest, visit kotest.io or see our quic

Aug 16, 2022
Fixtures for Kotlin providing generated values for unit testing

A tool to generate well-defined, but essentially random, input following the idea of constrained non-determinism.

Aug 15, 2022
Lightweight service for creating standalone mock, written in pure Kotlin with Netty container.

MockService The lightweight service for creating a standalone mock, written in pure Kotlin with Netty container. The service allows getting config fil

Oct 28, 2021
Proyecto de Kotlin y JPA sobre Hibernate, con algunos test usando JUnit 5 y Mockito.
Proyecto de Kotlin y JPA sobre Hibernate, con algunos test usando JUnit 5 y Mockito.

Contactos Kotlin JPA Ejemplos de una aplicación de manejo de contactos con Kotlin y JPA. Usando para testear la aplicación JUnit 5 y Mockito. Almacena

Dec 17, 2021