paulbutcher / ScalaMock

Native Scala mocking framework
http://scalamock.org/
MIT License
502 stars 99 forks source link

Cannot mock class that uses the "pimp my library" pattern #431

Closed mattseburn closed 2 years ago

mattseburn commented 2 years ago

If you want to discuss a new feature, please ignore/clear this form.

ScalaMock Version (e.g. 3.5.0)

5.1.0

Scala Version (e.g. 2.12)

2.12.13

Runtime (JVM or JS)

JVM

Please describe the expected behavior of the issue

Scalamock should be able to see the methods added by the implicit class.

Please provide a description of what actually happens

A java.lang.NoSuchMethodException is thrown.

Reproducible Test Case

Please provide a minimised code snippet that fails, ideally, written as a failing test case in ScalaTest. This will help us a lot in diagnosing the problem and work on a fix. If the issue is more complex or requires configuration, please provide a link to a project on Github that reproduces the issue.

  class Greeter {
    def sayHello(name: String): String =
      s"Hello $name!"
  }

  object PimpedLibrary {
    implicit class AdditionalMethods(greeter: Greeter) {
      def enhancedSayHello(name: String, message: String): String =
        s"${greeter.sayHello(name)}, $message"
    }
  }

  class ClassUnderTest {
    import PimpedLibrary._

    def methodUnderTest(greeter: Greeter): String =
      greeter.enhancedSayHello("world", "how are you today?")
  }

  "Greeter" in {
    import PimpedLibrary._

    val mockGreeter = mock[Greeter]

    val expectedName = "world"
    val expectedMessage = "how are you today?"
    val expectedResult = s"$expectedName, $expectedMessage"

    val classUnderTest = new ClassUnderTest()

    (mockGreeter.enhancedSayHello(_: String, _: String))
      .expects(expectedName, expectedMessage)
      .returning(expectedResult)

    classUnderTest.methodUnderTest(mockGreeter) shouldEqual expectedResult
  }
barkhorn commented 2 years ago

Scalamock should be able to see the methods added by the implicit class.

The implicit class does not 'add' these methods to the Greeter class, so they are in fact not visible. The method you are calling is in the implicit class AdditionalMethods which is not mocked in your code. This won't work I'm afraid.