Skip to content

0.3.1 Mock creation in thenReturn fails (works with scalatest mockitosugar) #35

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

Closed
aselamal opened this issue Aug 23, 2018 · 2 comments
Closed

Comments

@aselamal
Copy link

So I have a weird error that I've tried to narrow down to a simple scenario. Basically If I try to create a mock in the thenReturn method of stubbing it fails at runtime. It works if the mock is created before and also works if I'm using the scala test mockito sugar, not really sure what is going on here.

package example

import org.mockito.MockitoSugar
import org.scalatest.WordSpec

case class AClass(property: Set[String])

class DoStuff {

    def doMethod(): AClass = {
        // we are going to mock this anyway
        ???
    }
}

class MockitoScalaSpec extends WordSpec with MockitoSugar {

    "Mock works" in {
        val a = mock[AClass]
        val worker = mock[DoStuff]
        when(worker.doMethod()).thenReturn(a)

    }

    "Mock inside then return doesn't work" in {
        val worker = mock[DoStuff]
        when(worker.doMethod()).thenReturn(mock[AClass])

    }

    "Does work for scala test inside then return doesn't work" in {
        val worker = org.scalatest.mockito.MockitoSugar.mock[DoStuff]
        when(worker.doMethod()).thenReturn(org.scalatest.mockito.MockitoSugar.mock[AClass])

    }

}

Only Mock inside then return doesn't work and it fails with


Calling public scala.collection.immutable.Set example.AClass$MockitoMock$676536933.copy$default$1() on Mock for AClass, hashCode: 585074510 with args []
java.lang.RuntimeException: Calling public scala.collection.immutable.Set example.AClass$MockitoMock$676536933.copy$default$1() on Mock for AClass, hashCode: 585074510 with args []
	at org.mockito.MockitoEnhancerUtil.call(MockitoEnhancerUtil.java:67)
	at org.mockito.MockitoEnhancerUtil.lambda$stubDefaultMethods$4(MockitoEnhancerUtil.java:56)
	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.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	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.mockito.MockitoEnhancerUtil.stubDefaultMethods(MockitoEnhancerUtil.java:56)
	at org.mockito.MockitoEnhancerUtil.stubAllDefaultMethods(MockitoEnhancerUtil.java:49)
	at org.mockito.MockitoSugar.stubMock(MockitoSugar.scala:4)
	at org.mockito.MockitoSugar.stubMock$(MockitoSugar.scala:4)
	at example.MockitoScalaSpec.stubMock(MockitoScalaSpec.scala:16)
	at org.mockito.MockitoEnhancer.mock(MockitoAPI.scala:144)
	at org.mockito.MockitoEnhancer.mock$(MockitoAPI.scala:137)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	at org.mockito.MockitoEnhancer.mock(MockitoAPI.scala:104)
	at org.mockito.MockitoEnhancer.mock$(MockitoAPI.scala:104)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	at example.MockitoScalaSpec.$anonfun$new$2(MockitoScalaSpec.scala:27)
	at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
	at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
	at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
	at org.scalatest.Transformer.apply(Transformer.scala:22)
	at org.scalatest.Transformer.apply(Transformer.scala:20)
	at org.scalatest.WordSpecLike$$anon$1.apply(WordSpecLike.scala:1078)
	at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
	at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
	at org.scalatest.WordSpec.withFixture(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.invokeWithFixture$1(WordSpecLike.scala:1076)
	at org.scalatest.WordSpecLike.$anonfun$runTest$1(WordSpecLike.scala:1088)
	at org.scalatest.SuperEngine.runTestImpl(Engine.scala:289)
	at org.scalatest.WordSpecLike.runTest(WordSpecLike.scala:1088)
	at org.scalatest.WordSpecLike.runTest$(WordSpecLike.scala:1070)
	at org.scalatest.WordSpec.runTest(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.$anonfun$runTests$1(WordSpecLike.scala:1147)
	at org.scalatest.SuperEngine.$anonfun$runTestsInBranch$1(Engine.scala:396)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at org.scalatest.SuperEngine.traverseSubNodes$1(Engine.scala:384)
	at org.scalatest.SuperEngine.runTestsInBranch(Engine.scala:379)
	at org.scalatest.SuperEngine.runTestsImpl(Engine.scala:461)
	at org.scalatest.WordSpecLike.runTests(WordSpecLike.scala:1147)
	at org.scalatest.WordSpecLike.runTests$(WordSpecLike.scala:1146)
	at org.scalatest.WordSpec.runTests(WordSpec.scala:1881)
	at org.scalatest.Suite.run(Suite.scala:1147)
	at org.scalatest.Suite.run$(Suite.scala:1129)
	at org.scalatest.WordSpec.org$scalatest$WordSpecLike$$super$run(WordSpec.scala:1881)
	at org.scalatest.WordSpecLike.$anonfun$run$1(WordSpecLike.scala:1192)
	at org.scalatest.SuperEngine.runImpl(Engine.scala:521)
	at org.scalatest.WordSpecLike.run(WordSpecLike.scala:1192)
	at org.scalatest.WordSpecLike.run$(WordSpecLike.scala:1190)
	at org.scalatest.WordSpec.run(WordSpec.scala:1881)
	at org.scalatest.tools.SuiteRunner.run(SuiteRunner.scala:45)
	at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13(Runner.scala:1346)
	at org.scalatest.tools.Runner$.$anonfun$doRunRunRunDaDoRunRun$13$adapted(Runner.scala:1340)
	at scala.collection.immutable.List.foreach(List.scala:389)
	at org.scalatest.tools.Runner$.doRunRunRunDaDoRunRun(Runner.scala:1340)
	at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24(Runner.scala:1031)
	at org.scalatest.tools.Runner$.$anonfun$runOptionallyWithPassFailReporter$24$adapted(Runner.scala:1010)
	at org.scalatest.tools.Runner$.withClassLoaderAndDispatchReporter(Runner.scala:1506)
	at org.scalatest.tools.Runner$.runOptionallyWithPassFailReporter(Runner.scala:1010)
	at org.scalatest.tools.Runner$.run(Runner.scala:850)
	at org.scalatest.tools.Runner.run(Runner.scala)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.runScalaTest2(ScalaTestRunner.java:131)
	at org.jetbrains.plugins.scala.testingSupport.scalaTest.ScalaTestRunner.main(ScalaTestRunner.java:28)
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 org.mockito.MockitoEnhancerUtil.call(MockitoEnhancerUtil.java:64)
	... 68 more
Caused by: org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at example.MockitoScalaSpec.when(MockitoScalaSpec.scala:16)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

	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 java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	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 example.MockitoScalaSpec.stubMock(MockitoScalaSpec.scala:16)
	at example.MockitoScalaSpec.mock(MockitoScalaSpec.scala:16)
	... 47 more



Using

object Dependencies {
  lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.5"
  lazy val mockitoScala = "org.mockito" %% "mockito-scala" % "0.3.1"
}
@ultrasecreth
Copy link
Member

That is related to the current implementation, basically when you create a mock, under the hood, it uses reflection to look for the default argument methods and stub them accordingly, thing is, Mockito doesn't allow to stub 2 mocks at the same time hence the fail.

PR #30 solves this as I got rid of the reflection stuff in favor of an improved default answer, but in the meantime you have 3 ways to overcome this

a) creating the mock before as you did
b) using the doReturn syntax, i.e. doReturn(mock[AClass]).when(worker).doMethod()
c) using the idiomatic syntax, i.e.

class MockitoScalaSpec extends WordSpec with IdiomaticMockito {

    "Mock inside shouldReturn does work" in {
        val worker = mock[DoStuff]
        worker.doMethod() shouldReturn mock[AClass]
      }
    }

@ultrasecreth
Copy link
Member

Fixed on #30

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