Code Monkey home page Code Monkey logo

mokkery's People

Contributors

lupuuss avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

mokkery's Issues

Kotlin 2.0.20

Kotlin 2.0.20-Beta1 seems to introduce multiple breaking changes that seems trivial to fix. However, fixing them in a backward compatible way might not be possible.

Provide a way to block the return from a mocked suspend function

Sometimes you need to test a state that is present while a suspending call is being made. For example, loading is true while the suspending call is still being executed.

So you need a way to have a mocked suspend function not return immediately but only return when you tell it to. Here is the way i am handling it now, but it would be nice to have support for this built-in

I created a mutable map to record what calls are being blocked:

    val deferred = mutableMap<Any, CompletableDeferred<Unit>>()

    fun Any.whilePaused(block: () -> Unit) {
        try {
            deferred[this] = CompletableDeferred()
            block()
        }
        finally {
            deferred.remove(this)?.complete(Unit)
        }
    }

Then in any suspend mock set up that i need to support blocking I have to do this (In this case it is a fun interface being mocked):

    val fooBar =
        mock<FooBar> {
            everySuspend { invoke(any()) } calls {
                success(returnValue)
                    .also { deferred[this@mock]?.await() }
            }
        }

This then lets me do tests like this:

    fooBar.whilePaused {
        sut.doLoad()
        assertTrue(sut.loading)
    }

    assertFalse(sut.loading)

Not able to verify objects by their content

Hello!
I've found an issue with verifying the objects when the contents are the same but instances are not.
Here is the error message:

Calls to the same method with failing matchers:
  ByteArrayParser(1).doNothing(id = UUID@fcb4004, value = [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33])
    [-] id:
       expect: UUID@8c11eee
       actual: UUID@fcb4004
    [-] value:
       expect: [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]
       actual: [72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]

As one can see the contents of byte array are the same. Also I am using the any() matcher so it should not matter if the contents are the same at the first place.

The minimal reproducible example is attached.
multiplatform-library-template.zip
Tested on Mac with apple chip and on windows

Mocks incompatible with value classes

It seems that using value class, e.g. kotlin.Result in mocks will fail the test with exception

Given the interface

interface TestInterfaceWithValueClass {
    fun test(): Result<String>
}

Calling the test

    @Test
    fun testReturnsMockableInterfaceWithValueClassImpl() {
        val mocked = mock<TestInterfaceWithValueClass> {
            every { test() } returns Result.success("test")
        }
        assertEquals(Result.success("test"), mocked.test())
    }

Will fail with exception

java.lang.NullPointerException: Cannot invoke "kotlin.Result.unbox-impl()" because the return value of "dev.mokkery.internal.MokkeryInterceptor.interceptCall(dev.mokkery.internal.CallContext)" is null
	at dev.mokkery.test.TestInterfaceWithValueClassb7d4c11efdfd4d2aa2c67574e6dd5d5eMock.test-d1pmJ48(MockTest.kt)
	at dev.mokkery.test.MockTest$testReturnsMockableInterfaceWithValueClassImpl$mocked$1$1.invoke-IoAF18A(MockTest.kt:23)
	at dev.mokkery.test.MockTest$testReturnsMockableInterfaceWithValueClassImpl$mocked$1$1.invoke(MockTest.kt)
	at dev.mokkery.internal.EveryKt.internalEvery(Every.kt:21)
	at dev.mokkery.test.MockTest$testReturnsMockableInterfaceWithValueClassImpl$mocked$1.invoke(MockTest.kt)
	at dev.mokkery.test.MockTest$testReturnsMockableInterfaceWithValueClassImpl$mocked$1.invoke(MockTest.kt:22)
	at dev.mokkery.test.TestInterfaceWithValueClassb7d4c11efdfd4d2aa2c67574e6dd5d5eMock.<init>(MockTest.kt)
	at dev.mokkery.test.MockTest.testReturnsMockableInterfaceWithValueClassImpl(MockTest.kt:22)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	...

mokkery version: 1.9.23-1.6.0
kotlin version: 1.9.23

no such method: ContextIndependentParameterRenderer

mokkery: 2.1.1
ksp: 2.0.20-Beta2-1.0.23
kotlin: 2.0.20-Beta2

When attempting migration to the latest kotlin/ksp versions we started noticing the following issue when running ./gradlew :shared:compileTestKotlinIosArm64

e: java.lang.NoSuchMethodError: 'org.jetbrains.kotlin.diagnostics.rendering.ContextIndependentParameterRenderer org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.getRENDER_TYPE()'
        at dev.mokkery.plugin.diagnostics.MokkeryDiagnosticRendererFactory.<init>(MokkeryDiagnosticRendererFactory.kt:16)
        at dev.mokkery.plugin.MokkeryCompilerPluginRegistrar.registerExtensions(MokkeryCompilerPluginRegistrar.kt:21)

full log: mokkery-error.log

Provide a short hand way to define every/everySuspend with all arg matchers set to any()

In most of my use of Mocking I set up mocks without checking parameters of the call in the setup and instead check parameters in verification. It would be nice to have a way to define that without having to specify all the any() parameters. The way that could be done is with method references

So from the examples:

val repository = mock<BookRepository> {
   everySuspend { findById(any()) } calls { (id: String) -> Book(id) }
}

Would be able to be replaced by:

val repository = mock<BookRepository> {
   everySuspend(this::findById) calls { (id: String) -> Book(id) }
}

Mocked interface doesn't return the value already set with every

During solving migration issues another issue come up, previously passing test start failing. I narrow down the issue, and it looks like mocked interface doesn't return the value already set with every. Maybe it is again some behavioral difference of Mokkery but couldn't be sure.

You can see the code piece in the PR

Let me know if anything is needed from my end!

Provide way to return a computed value not just a straight value with returns/returnsSuccess

I have a lot of boilerplate mocks set up like this where I have a bunch of var properties defining the data which can then be modified and then would like to use returns/returnsSuccess with the property instead of call.

So using the example from the docs it currently looks something like this:

var book = Book(1)

val repository = mock<BookRepository> {
   everySuspend { findById(any()) } calls { book }
}

reading the code it doesn't really represent what it is doing. calls is only used because we need to get the current value of the property. And when the return value is result there is no callsSuccess

So my thought would be that there would be overloads of returns/returnsSuccess that instead of a value of type T take a lambda of type () -> T

Then one could instead say something more like

val repository = mock<BookRepository> {
   everySuspend { findById(any()) } returns { book }
}

or

val repository = mock<BookRepository> {
   everySuspend { findById(any()) } returns(::book)
}

and for the case where the type is a Result

val repository = mock<BookRepository> {
   everySuspend { findById(any()) } returnsSuccess { book }
}

MockMode.autoUnit does not work when mocking functional types

AutoUnit does not work for functional types.

The first test from the example below will fail, while the second one is successful.

Kotlin multiplatform version: 1.9.24
Kotlin multiplatform target: js
Mokkery version: 1.9.24-1.7.0

interface TestInterface {
    fun invokeInterface(foo: Int)
}

class Example {

    @Test
    fun testAutoUnitDoesNotWorkForFunction() {
        val functionMock = mock<(foo: Int) -> Unit>(MockMode.autoUnit)
        functionMock.invoke(1) // Fails with CallNotMockedException: Call Function1(1).invoke(p1 = 1) not mocked!
    }

    @Test
    fun testAutoUnitWorkForInterface() {
        val functionMock = mock<TestInterface>(MockMode.autoUnit)
        functionMock.invokeInterface(1) // success
    }
}

Is not possible to mock a `data class`

I have the implementation of this data class:

@Serializable
data class WordPair(
    val wordsTotal: Int,
    val wordsFound: List<String>
)

at first run, I get this error:

Type ''com.alejandrorios.bogglemultiplatform.data.models.WordPair'' is final and cannot be used with ''mock''!

which I know it is because of one of the limitations of the library, then I'm including the @OpenForMokkery annotation to the data class, and now I get this error:

Class ''com.alejandrorios.bogglemultiplatform.data.models.WordPair'' has no default constructor and cannot be used with ''mock''!

Is it possible to solve this without adding default values to the data class?, maybe I'm missing something else.

Kotlin 2.0.0 support

Hey team Mokkery,

This is more of an information request than an issue, just wondering, if and when we can expect support for Kotlin 2.0?

I'm aware it's still in beta, but we'd love to start testing it asap, but since mokkery is a crucial part of the application we're a bit blocked.

Best,
-martin

NullPointerException thrown during migration

Hello,

Thank you for this amazing mocking library, thanks to it, I get rid of ksp and decreased my build times, also finally I was able to move my project to Kotlin 2.0.

During the migration from Mockative to Mokkery I had various issues and couldn't fix 3 of them. This issue is targeting to one of it.

If you check the linked PR, I have commented out one verify line. This line was working fine with Mockative, I had to comment it during Mokkery migration since it was giving the below error:

    java.lang.NullPointerException at AdControlRepositoryTest.kt:225

You can see the full log in the link I shared below.

Let me know if anything is needed from my end!

Log: https://github.com/Oztechan/CCC/actions/runs/9614886435/job/26546544559?pr=3581
PR: Oztechan/CCC#3581

Wasm-WASI Coroutines support

Currently, Mokkery does not support coroutines for Wasm-WASI because coroutines do not support this target. Support for this target will be available with coroutines version 1.9.0.

NoSuchElementException thrown during migration

Hello,

Thank you for this amazing mocking library, thanks to it, I get rid of ksp and decreased my build times, also finally I was able to move my project to Kotlin 2.0.

During the migration from Mockative to Mokkery I had various issues and couldn't fix 3 of them. This issue is targeting to one of it.

If you check the linked PR, I have commented out one test case. This test case was working fine with Mockative, I had to comment it during Mokkery migration since it was giving the below error:

java.util.NoSuchElementException at MainViewModelTest.kt:105

You can see the full log in the link I shared below.

Let me know if anything is needed from my end!

Log: https://github.com/Oztechan/CCC/actions/runs/9614855462/job/26520671149?pr=3579
PR: Oztechan/CCC#3579

NotImplementedError Error thrown during migration

Hello,

Thank you for this amazing mocking library, thanks to it I get rid of ksp and decreased my build times, also finally I was able to move my project to Kotlin 2.0.

During the migration from Mockative to Mokkery I had various issues and couldn't fix 3 of them. This issue is targeting to one of it.

If you check the linked PR, I have added 3 test classes back(These test classes were working fine with Mockative), I had to remove these classes during Mokkery migration since it was giving the below error:

e: Compilation failed: Generation of stubs for class org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterPublicSymbolImpl is not supported yet

 * Source files: 
 * Compiler version: 2.0.0
 * Output kind: PROGRAM

e: kotlin.NotImplementedError: Generation of stubs for class org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterPublicSymbolImpl is not supported yet
	at org.jetbrains.kotlin.backend.common.linkage.partial.MissingDeclarationStubGenerator.getDeclaration(MissingDeclarationStubGenerator.kt:62)
	at org.jetbrains.kotlin.backend.common.linkage.partial.ClassifierExplorer.exploreSymbol(ClassifierExplorer.kt:96)
	at org.jetbrains.kotlin.backend.common.linkage.partial.ClassifierExplorer.exploreType(ClassifierExplorer.kt:75)
	at org.jetbrains.kotlin.backend.common.linkage.partial.ClassifierExplorer.exploreType(ClassifierExplorer.kt:65)
	at org.jetbrains.kotlin.backend.common.linkage.partial.PartiallyLinkedIrTreePatcher.explore(PartiallyLinkedIrTreePatcher.kt:946)
	at org.jetbrains.kotlin.backend.common.linkage.partial.PartiallyLinkedIrTreePatcher.toPartiallyLinkedMarkerTypeOrNull(PartiallyLinkedIrTreePatcher.kt:949)
	at org.jetbrains.kotlin.backend.common.linkage.partial.PartiallyLinkedIrTreePatcher.access$toPartiallyLinkedMarkerTypeOrNull(PartiallyLinkedIrTreePatcher.kt:43)
	at org.jetbrains.kotlin.backend.common.linkage.partial.PartiallyLinkedIrTreePatcher$DeclarationTransformer.rewriteTypesInFunction(PartiallyLinkedIrTreePatcher.kt:387)
	at org.jetbrains.kotlin.backend.common.linkage.partial.PartiallyLinkedIrTreePatcher$DeclarationTransformer.visitSimpleFunction(PartiallyLinkedIrTreePatcher.kt:265)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:131)
	at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitSimpleFunction(IrElementTransformerVoid.kt:19)

You can see the full log in the link I shared below.

Let me know if anything is needed from my end!

Log: https://github.com/Oztechan/CCC/actions/runs/9615001222/job/26521152675?pr=3583
PR: Oztechan/CCC#3583

Recommend Projects

  • React photo React

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

  • Vue.js photo Vue.js

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

  • Typescript photo Typescript

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

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

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

  • web

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

  • server

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

  • Machine learning

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

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

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

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.