ScalaMock如何mock包含重载柯里化传名参数方法的trait?
ScalaMock 5.1 重载带传名参数方法的正确Mock写法
Scala 2.13 + ScalaMock 5.1 完全支持mock该trait中的两个重载bar方法,你之前的写法报错核心是两个问题:
- 没有显式给方法指定签名,导致编译器无法区分两个重载的
bar方法 - 错误将传名参数类型
=> Double等同于无参函数类型() => Double,且多余的下划线语法使用错误
各报错原因说明
- 第一种写法报错:末尾多余的
_相当于尝试将已经完成参数占位的方法再转为函数,不符合语法要求 - 第二、第三种写法报错:你将第二个参数列表的传名参数
=> Double错误声明为() => Double,二者是Scala中完全不同的类型,触发类型不匹配 - 第四种写法报错:没有给方法显式声明类型,编译器无法从上下文中判断你要mock的是单参数还是双参数列表的重载方法,因此报无法解析重载方法
正确Mock写法
1. Mock双参数列表带传名参数的bar方法
两种常用写法,均需先显式指定方法签名消除重载歧义:
expects风格写法
val mockFoo = mock[Foo] // 显式声明方法签名,帮编译器定位到目标重载方法 val targetBar: (Int, => Double) => Double = mockFoo.bar(_: Int)(_: Double) // 匹配入参第一个为1,第二个传名参数任意,返回2.0 targetBar.expects(1, *).returns(2.0)
when风格写法
val mockFoo = mock[Foo] val targetBar: Int => (=> Double) => Double = mockFoo.bar when(targetBar(1)(*)).thenReturn(2.0)
2. Mock单参数列表的bar方法
同理显式指定签名即可:
val mockFoo = mock[Foo] val singleBar: Double => Double = mockFoo.bar // 匹配入参为1.0时返回3.0 singleBar.expects(1.0).returns(3.0)
验证效果
调用mock后的方法符合预期,且传名参数不会实际执行:
val res1 = mockFoo.bar(1) { println("这段代码不会执行") 100.0 } // res1 = 2.0 val res2 = mockFoo.bar(1.0) // res2 = 3.0
内容的提问来源于stack exchange,提问作者Daryl Odnert
相关产品推荐
相关产品推荐

