ScalaMock模拟通用Java接口重载方法

时间:2018-04-25 12:32:58

标签: java scala unit-testing generics scalamock

我正在尝试使用不同数量的参数来模拟具有重载方法的Java通用接口。 接口代码是:

if a[text.Text] then ...

我尝试使用onComplete功能模拟发送,如下所示:

import java.util.concurrent.Callable

import java.util.concurrent.Callable;

public interface GOInterface<T> {
    void send(T record);
    void send(T record, Callable<T> onComplete);
}

我从编译器得到的错误是:

import org.scalamock.scalatest.MockFactory
import org.scalatest.{FlatSpec, Matchers}

class JavaInterfaceTest extends FlatSpec with Matchers with MockFactory {
  behavior of "scalamock"

  it should "mock java generic interface with overloaded method (with different number of parameters)" in {
    var result = ""
    val m = mock[GOInterface[String]]
    (m.send(_: String, _: Callable[String])).expects(*, *)
      .onCall{ case(s: String, c: Callable[String]) => c.call()}.once

    m.send("hello", new Callable[String] {
      override def call(): String = {result = "world"; result}
    })

    result should be("world")
  }


  it should "mock java generic interface with overloaded method (with different number of parameters) 2" in {
    var result = ""
    val m = mock[GOInterface[String]]
    (m.send(_: String)).expects(*).once

    m.send("hello")

    result should be("")
  }
}

查看ScalaMock git中的不同示例我可以看到没有测试通过具有不同参数计数的重载方法来检查通用接口。

我的依赖关系是:

error: value expects is not a member of (String, java.util.concurrent.Callable[String]) => Unit
[ERROR]     (m.send(_: String, _: Callable[String])).expects(*, *)
[ERROR]                                              ^

error: value expects is not a member of String => Unit
[ERROR]     (m.send(_: String)).expects(*).once
[ERROR]    

我同时在ScalaMock仓库中创建了bug

2 个答案:

答案 0 :(得分:1)

首先,我建议升级到ScalaMock的最新版本,但也可能存在围绕泛型和重载的极端情况。

要解决这个问题,在许多情况下,首先锁定类型会有所帮助,然后创建一个模拟:

trait StringGoInterface extends GoInterface[String]
val m = mock[StringGoInterface]

答案 1 :(得分:1)

我设法克服了这个问题。不是最干净的方式,而是它的作品。 正如@PhilippM建议我需要修复类型,但不幸的是,这还不够,我需要创建一个虚拟类。 这是为我工作的解决方案:

class JavaInterfaceTest extends FlatSpec with Matchers with MockFactory {
  behavior of "scalamock"

  class StringInterface extends GOInterface[String] {
    override def send(record: String): Unit = ()

    override def send(record: String, onComplete: Callable[String]): Unit = ()
  }

  val call: (String, Callable[String]) => Unit = { case(s: String, c: Callable[String]) => c.call()}

  it should "mock java generic interface with overloaded method (with different number of parameters)" in {
    var result = ""
    val m = mock[StringInterface]
    (m.send(_: String, _: Callable[String])).expects(*, *)
      .onCall{ call }.once

    m.send("hello", new Callable[String] {
      override def call(): String = {result = "world"; result}
    })

    result should be("world")
  }


  it should "mock java generic interface with overloaded method (with different number of parameters) 2" in {
    var result = ""
    val m = mock[StringInterface]
    (m.send(_: String)).expects(*).once

    m.send("hello")

    result should be("")
  }
}

我发现这有点难看,当需要嘲笑更复杂的接口时可能会更糟,但我希望它可以帮助其他人。