question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Recognize atLeast = 0

See original GitHub issue

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.

Prerequisites

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

Failure Information (for bugs)

Minimal reproducible code (the gist of this issue)

class AtLeastTest {
    class MockCls {
        fun op(x: Int) = Unit
    }

    @Test
    fun `at least=0 should be considered`() {
        val mock = mockk<MockCls>()
        justRun { mock.op(any()) }
        mock.op(0)
        verify(atLeast = 0, atMost = 1) { mock.op(1) }
    }
}

should pass

Current Behavior

doesn’t pass

Context

  • MockK version: latest(1.12.3)

Stack trace

// -----------------------[ YOUR STACK STARTS HERE ] -----------------------
Verification failed: call 1 of 1: MockCls(#1).op(eq(1))). Only one matching call to MockCls(#1)/op(Int) happened, but arguments are not matching:
[0]: argument: 0, matcher: eq(1), result: -

Stack trace:
                                                                                   io.mockk.impl.InternalPlatform.captureStackTrace               (InternalPlatform.kt:125)                          
                                                                                     io.mockk.impl.stub.MockKStub.handleInvocation                (MockKStub.kt:250)                                 
                                                   io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation                      (JvmMockFactoryHelper.kt:23)                       
                                                                            io.mockk.proxy.jvm.advice.Interceptor.call                            (Interceptor.kt:21)   
// -----------------------[ YOUR STACK TRACE ENDS HERE ] -----------------------

Possibly changing default value of atLeast to 0 is needed since mathematicians will think verify(atMost=3) will be <= 3.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:1
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
lucaslscommented, Nov 16, 2022

I found a solution, instead of:

verify(atLeast = 0, atMost = 3) { foo.bar() }

Write it using the inverse param:

verify(inverse = true, atLeast = 4) { foo.bar() }

This means the test will fail when at least 4 calls are made, in other words, it will succeed if at most 3 calls are made. including no calls at all.

If you want more clarity, you can create a function:

fun verifyOptionally(
    atMost: Int = 1,
    verifyBlock: MockKVerificationScope.() -> Unit
) = verify(
    inverse = true,
    atLeast = atMost + 1,
    verifyBlock = verifyBlock,
)

I have a valid use case: I want data is being cached and not retrieved multiple times on integration tests, that have shared resources between Test methods (Spring Boot tests always share resources on a Test class level). As I can’t control the order tests will run, I need to ensure a method is called at most once, which includes not being called at all. It’d be great if this was supported out of the box.

1reaction
orcchgcommented, Jul 30, 2022

I can give a use case where this is relevant

suppose, we have a random generation inside SUT (system-under-test), like that:

class SUT(val hook: Hook) {

    fun getData() {
        val previousData = getDataFromCache()
        var data = createRandomData()
        while (hasIntersection(data, previousData)) {
            data = createRandomData() // <-- recreate
            hook.TEST_DATA_RECREATE()
        }
        ... // cache new data and return
    }
}

it maintains a cache of previous data but for some reason - wants new data and previous data to have nothing in common - like, no intersection. If there is intersection, recreate new data - remember, it runs some random algorithm inside, so it might or might not end up with the new data that would have some intersection with the previous data.

In tests, I’d like to control the number of recreations, if they actually happen, to prevent from infinite looping and tests against it. For example:

val mockHook = mocks<Hook>()
val sut = SUT(mockHook)

@Test
fun `test get data - deterministic random - should run 3 times before getting brand new data`() {
    every { random.nextInt() } returnsMany listOf(0, 0, 0, 999) // 3 times same data, 4th time - new data
    
    val data = sut.getData()
    
    verify(atLeast = 3) { mockHook.TEST_DATA_RECREATE }
}

so it’s okay here. But now I’d like to test REAL scenario, where randomness in true random:

@Test
fun `test get data - true random - should run 3 times before getting brand new data`() {
    val data = sut.getData()
    
    verify(atLeast = 0) { mockHook.TEST_DATA_RECREATE }
}

here atLeast = 0 is justified - I don’t know in advance, whether my data will have any intersection with the previous data or not, but I’d like still to definitely distinguish this from the case, where there is NO calls to hook at all. So, in this example:

atLeast = 0 is needed and it’s VERY different from exactly = 0.

In reality, atLeast = 0 doesn’t work at all. Because it failed with the following message:

Verification failed: call 1 of 1: Hook(#19).TEST_DATA_RECREATE$shared_debug(any())) was not called.

but I want to clearly distinguish it from exactly = 0 as mentioned above. Whether it’s called or not - I need to check that, but I can’t be sure that it will always be exactly = 0 - i.e. no calls at all.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Recognize Zero - ScienceDirect.com
real and complex numbers can we recognize zero? In the following section a definition is given for a subset of the complex numbers...
Read more >
Homework 3 Solutions - NJIT
Homework 3 Solutions. 1. Give NFAs with the specified number of states recognizing each of the following lan- guages. In all cases, the...
Read more >
The Origin of Zero - Scientific American
"There are at least two discoveries, or inventions, of zero," says Charles Seife, author of Zero: The Biography of a Dangerous Idea (Viking, ......
Read more >
DFA machines accepting odd number of 0's or/and even ...
Now start designing all the DFAs one by one: Odd number of 0's or even number of 1's: This machine accept that languages...
Read more >
Chapter 4 - O-1 Beneficiaries - USCIS
In all cases, an O-1 beneficiary's achievements must have been recognized in the ... if applicable), or at least three of the applicable...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found