ScalaMock icon indicating copy to clipboard operation
ScalaMock copied to clipboard

Overloaded methods with parameters passed by-name cannot be mocked

Open ruado1987 opened this issue 11 years ago • 11 comments

I m using ScalaMock to create a stub of the FileSystemManager interface but keep encountering error during compile time because ScalaMock 3 is unable to resolve the overloaded method FileObject resolveFile(String name, FileSystemOptions fileSystemOptions). Here is the test demonstrating this problem:


import org.scalatest.FunSuite
import org.scalamock.scalatest.MockFactory
import org.apache.commons.vfs2._

class OverloadedMethodSuite extends FunSuite with MockFactory {

    test("stub an overloaded method") {
        val s = stub[FileSystemManager]

        // ScalaMock 3 is failing at the next line
        (s.resolveFile(_: String, _: FileSystemOptions)).when("test", null).returns(null)

        assert(s.resolveFile("test", null) == null)
    }
}

The error message is as follows:

: Unable to resolve overloaded method resolveFile [info] (m.resolveFile(_: String, _: FileSystemOptions)).when("test", null).returns(null)

ruado1987 avatar Apr 17 '13 09:04 ruado1987

I am having the same problem when trying to mock PrintStream#print(_: String). Did you find a solution?

simao avatar May 27 '13 21:05 simao

I'm also affected by this issue. But the compiler error only happens when one of the overloaded methods has a call-by-name argument. This code:

class OverloadedTest extends FunSpec with MockFactory {

  trait ByName {
    def call(i: Int)(u: => Unit)
    def call()
  }

  describe("By name") {
    it("call overloaded method") {
      val byname = mock[ByName]
      (byname.call(_:Int)(_:Unit)).expects(10, *)
      byname.call(10)(print(""))
    }
  }
}

Results in: Unable to resolve overloaded method call (byname.call(:Int)(:Unit)).expects(10, *)

If I change def call(i: Int)(u: => Unit) to def call(i: Int)(u: Unit) or remove the overloaded def call() everything works fine.

zamblauskas avatar Jul 11 '13 12:07 zamblauskas

@ruado1987 In ScalaMock 3.2.1 you can mock FileSystemManager.resolveFile:

  "ScalaMock" should "stub FileSystemManager" in {
    import org.apache.commons.vfs2._

    val s = stub[FileSystemManager]
    (s.resolveFile(_: String, _: FileSystemOptions)) when ("test", null) returns (null)
    assert(s.resolveFile("test", null) == null)
  }

@simao In ScalaMock 3.2.1 you can mock PrintStream.print:

  it should "mock PrintStream" in {
    import java.io.{ OutputStream, PrintStream }
    class MockablePrintStream extends PrintStream(mock[OutputStream], false)

    val m = mock[MockablePrintStream]
    (m.print(_: String)) expects ("foo")
    m.print("foo")
  }

@zamblauskas You are right - overloaded methods with parameters passed by-name are not currently handled in ScalaMock. I will take care of this soon.

pawel-wiejacha avatar Dec 17 '14 19:12 pawel-wiejacha

@pawel-wiejacha the change of title isn't quite right, this is also affecting overloaded non passed-by-name methods if one of the parameters is a generic available to the trait.

trait OverloadedMultiParams[A] {
  def meth(i: Int, a: A): Int
  def meth(): Int
}

val mockTrait = mock[OverloadedMultiParams[String]]
(mockTrait.meth(_: Int, _: String)).expects(1, "Hello").returns(1)

This returns:

Information:(74, 20) Unable to resolve overloaded method meth
    (mockTrait.meth(_: Int, _: String)).expects(1, "Hello").returns(1)
                   ^

trane avatar Jan 27 '15 21:01 trane

@trane: thanks - I didn't know about this case. It's a different bug so I created separate issue (#93) for it.

Handling overloaded methods with parameters passed by name can be fixed if we use scala.reflect.internal API - I've dirty fix ready in my local repository.

pawel-wiejacha avatar Feb 03 '15 23:02 pawel-wiejacha

when will this issue be released ? need this fix. any workaround ?

sbhola avatar Apr 27 '17 05:04 sbhola

At the moment, ScalaMock 4, and fixes for issues like this, depend on Scala.Meta. This has now been released but only supports a subset of Scala versions and only the JVM backend, last time I checked. ScalaMock supports a wider range, so we cannot easily migrate. There are some fundamental limitations of macros. Second parameter lists are always a bit tricky to mock, I find. Maybe using a ProxyMock could be a workaround?

barkhorn avatar Apr 27 '17 07:04 barkhorn

@barkhorn Thank you for your prompt reply. Going forward with the proxy approach at this moment. Waiting for ScalaMock 4 with stability soon :)

sbhola avatar Apr 27 '17 07:04 sbhola

My current plan is to keep the 3.x series going as mainline until Scala.meta is available on at least 2.11, 2.12 and JVM+JS. At that time it's probably worth dropping 2.10 support from the 4.x series and doing a revamp to address all the macro problems. At the moment though, 2.10 remains popular due to Spark and SBT, so I am not prepared to make that jump just yet and would rather address some of the fixable issues first to get it as stable as possible.

barkhorn avatar Apr 27 '17 07:04 barkhorn

4.x is still the same as the 3.x series, however the library name and transitive dependencies are changed.

barkhorn avatar Nov 13 '18 15:11 barkhorn

Works with Scala 3

goshacodes avatar Feb 25 '24 10:02 goshacodes