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

Mockito cannot mock this class: class scala.xml.Elem #518

Open
glidester opened this issue Nov 27, 2023 · 1 comment
Open

Mockito cannot mock this class: class scala.xml.Elem #518

glidester opened this issue Nov 27, 2023 · 1 comment

Comments

@glidester
Copy link

I am upgrading an old service that had fallen behind on lib updates.

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.

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
}

class IssueSpec extends AnyWordSpec with Matchers with MockitoSugar {
  val generator = mock[ReturnsXml]

  "Mockito" should {
    "be able to mock a class" that {
      "returns a scala.xml value" in {
        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

@glidester
Copy link
Author

A kind soul gave me a work around for this issue on stackoverflow:
https://stackoverflow.com/questions/77556227/mockito-scala-mockito-cannot-mock-this-class-class-scala-xml-elem

The work around was to use the following style initialisation:
doReturn(<empty/>).when(generator).respond()

This works but it is not obvious why it works and the other does not. I'm leaving this issue open as it would still be good to fix the original style bug, or at the very least improve the generated error to include suggesting using this alternate style.

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

1 participant