如何使用ScalaMock模拟按名称调用的函数?
解决ScalaMock模拟按名称调用函数的问题
你的问题出在两个关键地方:类型转换错误和返回值不符合方法签名,咱们一步步来修正:
错误原因分析
- 按名称参数的类型误解:
f: => T是Scala的按名称参数,运行时它对应的是Function0[T](也就是() => T),而不是你写的() => Either[ErrorCode,T]。你把传入的futureFunction()的返回值(Future[Int])当成了Either类型,这就导致了类型转换异常。 - 返回值不匹配:
myFunction的返回类型是Either[ErrorCode, T],但你直接返回了f()的结果(Future[Int]),没有包装成Either,这也不符合方法的签名要求。
修正后的测试代码
我们可以用两种方式来实现正确的mock,推荐第二种更类型安全的写法:
写法1:通用类型匹配(适合任意T)
import scala.concurrent.{Future, Await} import scala.concurrent.duration._ import scala.util.Random import org.specs2.mutable.Specification import org.scalamock.scalatest.MockFactory // 假设你的ErrorCode定义如下 sealed trait ErrorCode case object UnknownError extends ErrorCode class MyTest extends Specification with MockFactory { trait MyTrait { def myFunction[T](id: Int, name: String)(f: => T): Either[ErrorCode, T] } def futureFunction(): Future[Int] = Future { Thread.sleep(Random.nextInt(500)) 10 } "Mock MyTrait" should { "execute the call-by-name parameter and return wrapped result" in { val mockTrait = mock[MyTrait] // 正确匹配按名称参数并处理 (mockTrait.myFunction(_: Int, _: String)(_: => T)) .expects(25, "test", *) .onCall { args => // 提取按名称参数对应的Function0[T] val callByNameFunc = args.productElement(2).asInstanceOf[() => T] // 执行函数并包装成Right返回,符合方法签名 Right(callByNameFunc()) } // 调用mock方法,注意需要等待Future完成 val result = mockTrait.myFunction(25, "test")(futureFunction()) val finalValue = Await.result(result.right.get, 1.second) finalValue mustEqual 10 } } }
写法2:指定具体类型(更安全,避免类型转换)
如果你的测试场景中T是固定的(比如这里是Future[Int]),可以直接指定类型,这样不需要用productElement做类型转换,代码更清晰:
// ... 其他代码不变 (mockTrait.myFunction(_: Int, _: String)(_: => Future[Int])) .expects(25, "test", *) .onCall { (id, name, f) => // f就是按名称参数,直接调用就会执行futureFunction() Right(f) } // ... 断言部分不变
关键要点总结
- 按名称参数
f: => T在ScalaMock中用_: => T来匹配,运行时对应Function0[T]。 - 必须保证mock的返回值符合原方法的签名:
Either[ErrorCode, T],所以要用Right(...)包装执行结果。 - 因为
futureFunction()返回Future[Int],所以myFunction的返回值是Either[ErrorCode, Future[Int]],需要用Await.result等待Future完成后再断言数值。
内容的提问来源于stack exchange,提问作者earlymorningtea
相关产品推荐
相关产品推荐

