After upgrading to "mockito-scala ->1.17.29" (and even tried specifying "mockito-core -> 2.22.0") I am now seeing this mockito error message when running my tests.
What is odd is that I'm not asking mockito to mock an instance of scala.xml.Elem, just to mock a class method that returns one.
If I wrap the returned Elem
object in a case class and return that in a method mockito is happy!
Here is a minimal example of this issue:
import org.mockito.MockitoSugar
import org.scalatest.matchers.must.Matchers
import org.scalatest.wordspec.AnyWordSpec
import scala.xml.Elem
trait ReturnsXml {
def respond(): Elem
def respondWrapped(): Wrapper
}
case class Wrapper(value: Elem)
class IssueSpec extends AnyWordSpec with Matchers with MockitoSugar {
val generator = mock[ReturnsXml]
"Mockito" should {
"be able to mock a class" that {
"returns a wrapped scala.xml value" in {
/* WORKS */
when(generator.respondWrapped()).thenReturn(Wrapper(<empty/>))
generator.respondWrapped() mustBe Wrapper(<empty/>)
}
"returns a scala.xml value" in {
/* ERRORS */
when(generator.respond()).thenReturn(<empty/>)
generator.respond() mustBe <empty/>
}
}
}
}
And here is the runtime error:
[info] - returns a scala.xml value *** FAILED ***
[info] org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: class scala.xml.Elem.
[info]
[info] Mockito can only mock non-private & non-final classes.
[info] If you're not sure why you're getting this error, please report to the mailing list.
[info]
[info]
[info] Java : 11
[info] JVM vendor name : AdoptOpenJDK
[info] JVM vendor version : 11.0.9.1+1
[info] JVM name : OpenJDK 64-Bit Server VM
[info] JVM version : 11.0.9.1+1
[info] JVM info : mixed mode
[info] OS name : Linux
[info] OS version : 5.4.0-167-generic
[info]
[info]
[info] Underlying exception : java.lang.IllegalStateException: java.lang.VerifyError: class scala.xml.Elem$MockitoMock$MKld2yOT overrides final method scala.collection.AbstractSeq.concat(Lscala/collection/IterableOnce;)Ljava/lang/Object;
[info] at scala.Option.orElse(Option.scala:477)
[info] at IssueSpec.$anonfun$new$3(IssueSpec.scala:22)
[info] at org.scalatest.OutcomeOf.outcomeOf(OutcomeOf.scala:85)
[info] at org.scalatest.OutcomeOf.outcomeOf$(OutcomeOf.scala:83)
[info] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info] at org.scalatest.Transformer.apply(Transformer.scala:22)
[info] at org.scalatest.Transformer.apply(Transformer.scala:20)
[info] at org.scalatest.wordspec.AnyWordSpecLike$$anon$3.apply(AnyWordSpecLike.scala:1076)
[info] at org.scalatest.TestSuite.withFixture(TestSuite.scala:196)
[info] at org.scalatest.TestSuite.withFixture$(TestSuite.scala:195)
[info] ...
[info] Cause: java.lang.IllegalStateException: java.lang.VerifyError: class scala.xml.Elem$MockitoMock$MKld2yOT overrides final method scala.collection.AbstractSeq.concat(Lscala/collection/IterableOnce;)Ljava/lang/Object;
[info] at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$UsingUnsafeInjection.defineClass(ClassInjector.java:1045)
[info] at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.injectRaw(ClassInjector.java:284)
[info] at net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase.inject(ClassInjector.java:118)
[info] at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$InjectionDispatcher.load(ClassLoadingStrategy.java:241)
[info] at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101)
[info] at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6166)
[info] at org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator.mockClass(SubclassBytecodeGenerator.java:289)
[info] at org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator.lambda$mockClass$0(TypeCachingBytecodeGenerator.java:47)
[info] at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:168)
[info] at net.bytebuddy.TypeCache$WithInlineExpunction.findOrInsert(TypeCache.java:399)
[info] ...
[info] Cause: java.lang.VerifyError: class scala.xml.Elem$MockitoMock$MKld2yOT overrides final method scala.collection.AbstractSeq.concat(Lscala/collection/IterableOnce;)Ljava/lang/Object;
[info] at java.base/java.lang.ClassLoader.defineClass1(Native Method)
[info] at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
[info] at java.base/java.lang.ClassLoader$ByteBuddyAccessor$V1.defineClass(Unknown Source)
[info] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[info] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[info] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[info] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[info] at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$UsingUnsafeInjection.defineClass(ClassInjector.java:1041)
[info] at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.injectRaw(ClassInjector.java:284)
[info] at net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase.inject(ClassInjector.java:118)
Can someone advise if this is a bug or am I missing something?
Thanks
P.S. Also raised this as an issue on the github repo: https://github.com/mockito/mockito-scala/issues/518
you have to change
when(generator.respond()).thenReturn(<empty/>)
for
doReturn(<empty/>).when(generator).respond()