Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to verify when spying on kotlin class #1851

Open
MFAshby opened this issue Dec 23, 2019 · 3 comments
Open

Unable to verify when spying on kotlin class #1851

MFAshby opened this issue Dec 23, 2019 · 3 comments

Comments

@MFAshby
Copy link

MFAshby commented Dec 23, 2019

I have a test class with 2 tests (written in java). The tests are trying to verify the behaviour of the subject (written in kotlin) by spying on it.

Expected behaviour:
tests pass because the expected method call is made.

Actual behaviour:
The first test passes, and the second (identical) test receives an UnfinishedVerificationException

Compilable example here:
https://github.com/MFAshby/spying-problem-sample

Problematic code:
SomeClass.kt:

package org.example

open class SomeClass {
    fun doThing1() {
        doThing2()
    }

    fun doThing2() {
        println("Hey")
    }
}

SpyingProblemTest.java:

package org.example;


import org.junit.Test;

import static org.mockito.Mockito.*;

public class SpyingProblemTest {
    private SomeClass underTest = spy(new SomeClass());

    @Test
    public void cantVerifySpies() {

        // WHEN
        underTest.doThing1();

        // THEN
        verify(underTest, times(1)).doThing2();
    }

    @Test
    public void cantVerifySpies2() {

        // WHEN
        underTest.doThing1();

        // THEN
        verify(underTest, times(1)).doThing2();
    }
}

Test output:

Hey
Hey

org.mockito.exceptions.misusing.UnfinishedVerificationException: 
Missing method call for verify(mock) here:
-> at org.example.SpyingProblemTest.cantVerifySpies(SpyingProblemTest.java:18)

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.


	at org.example.SpyingProblemTest.<init>(SpyingProblemTest.java:9)
	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 org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217)
	at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
	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.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)


Process finished with exit code 255

I originally logged this with mockito-kotlin but I subsequently reproduced the issue without that library, so I think the problem is in mockito.

Interesting version numbers:

<kotlin.version>1.3.61</kotlin.version>
<junit.version>4.12</junit.version>
<mockito-core.version>3.0.0</mockito-core.version>
@bohsen
Copy link

bohsen commented Apr 28, 2020

@MFAshby You have to use open on doThing2() function too or use mockito-inline.

Sry for not getting back to you on the original issue. Totally forgot.

@bohsen
Copy link

bohsen commented Apr 28, 2020

This works:

open class SomeClass {
   fun doThing1() {
        doThing2()
    }

    open fun doThing2() {
        println("Hey")
    }
}
public class SpyingProblemTest {
    private SomeClass underTest = spy(new SomeClass());

    @Test
    public void cantVerifySpies() {

        // WHEN
        underTest.doThing1();

        // THEN
        verify(underTest, times(1)).doThing2();
    }

    @Test
    public void cantVerifySpies2() {

        // WHEN
        underTest.doThing2();

        // THEN
        verify(underTest, times(1)).doThing2();
    }
}

@bohsen
Copy link

bohsen commented Apr 28, 2020

Maybe change your dependency on mockito-core to mockito-inline.

Replace mockito-core with this in your pom:

<dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>${mockito-inline.version}</version>
        <scope>test</scope>
</dependency>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants