例如,我开始依附于类型浓缩
object MyImplicits{
implicit class RichInt(i: Int){
def complexCalculation: Int = i * 200
}
}我在这样的代码中使用的
object Algorithm{
def apply(rand: Random) = {
import MyImplicits._
rand.nextInt.complexCalculation + 1
}
}但是我现在怎么能隔离和单元测试算法呢?特别是,我想嘲笑complexCalculation的实现,如下所示:
class MyAlgorithmTest extends FreeSpec with MockitoSugar{
import org.mockito.Mockito.when
"MyApgorithm" {
"Delegates complex calculation" in {
val mockRandom = mock[Random]
when(mockRandom.nextInt()).thenReturn(1)
// This wouldn't work, but is the kind of thing I'm looking for
//when(1.complexCalculation).thenReturn(2)
val expected = 1 * 2 + 1
val result = MyAlgorithm(mockRandom)
assert(result === expected)
}
}
}发布于 2016-09-02 06:35:05
当您有组合时,通常不需要模拟,因为您可以用实现来代替测试。尽管如此,在这种情况下,我并不是一个狂热的追求者,只是没有看到他们带来的价值。我会用旧的学校作文来解决这个问题(正如我在另一个评论中所暗示的):
trait Calculation {
def calculation(i: Int): Int
}
trait ComplexCalculation extends Calculation {
def calculation(i: Int): Int = i * 200
}
trait MyAlgorithm {
self: Calculation =>
def apply(rand: Random) = {
calculation(rand.nextInt) + 1
}
}
// somewehre in test package
trait MockCalculation extends Calculation {
def calculation(i: Int): Int = i * 200
}
//test instance
object MyAlgorithm extends MyAlgorithm with MockCalculation如果您坚持使用implicits来完成构图,您可以这样做:
trait Computation {
def compute(i: Int): Int
}
object prod {
implicit val comp = new Computation {
def compute(i: Int): Int = i * 200
}
}
object test {
implicit val comp = new Computation {
def compute(i: Int): Int = i + 2
}
}
object Algorithm {
def apply(rand: Random)(implicit comp: Computation) = {
comp.compute(i) + 1
}
}
// application site
import prod._
Algorithm(scala.util.Random) // will run * 200 computation
//test
import test._
Algorithm(scala.util.Random) // will run + 2 computation但是这不会给你一个计算的点语法。我的直觉也反对这种方法,因为这是定义行为的一种非常微妙的方法,而且很容易在所带来的重要意义上犯错误。
发布于 2016-08-31 04:22:23
RichInt.scala
trait RichInt {
def complexCalculation: Int
}
class RichIntImpl(i: Int) extends RichInt {
def complexCalculation = i * 200
}Algorithm.scala
import scala.util.Random
class Algorithm(enrich: Int => RichInt) {
implicit val _enrich = enrich
def apply(rand: Random) = {
rand.nextInt.complexCalculation + 1
}
}
object Algorithm extends Algorithm(new RichIntImpl(_))AlgorithmTest.scala
import org.scalatest.FreeSpec
import scala.util.Random
import org.mockito.Mockito._
class AlgorithmTest extends FreeSpec with MockSugar {
"MyApgorithm should" - {
"Delegate the complex calculation" in {
val mockRandom = mock[Random]
when(mockRandom.nextInt()) thenReturn 1
val algorithm = new Algorithm(
enrich = mocking[Int => RichInt] { enrich =>
when(enrich(1)).thenReturnMocking { richInt =>
when(richInt.complexCalculation).thenReturn(2)
}
}
)
val expected = 3
assert(algorithm(mockRandom) === expected)
}
}
}MockSuger.scala
import org.scalatest.mockito.MockitoSugar
import org.mockito.stubbing.OngoingStubbing
// More sugars to make our tests look better.
trait MockSugar extends MockitoSugar {
def mocking[T <: AnyRef : Manifest](behavior: T => Unit): T = {
val m = mock[T]
behavior(m)
m
}
implicit class RichOngoingStubbing[T <: AnyRef : Manifest](stub: OngoingStubbing[T]) {
def thenReturnMocking(behavior: T => Unit) = {
val m = mock[T]
val s = stub.thenReturn(m)
behavior(m)
s
}
}
}发布于 2016-08-24 15:29:54
下面使用的是最可缩放的api。模拟测试运行良好,隐式类转换正常。
// Implicit.scala in src/main/scala
package implicittesting
import scala.util.Random
object MyImplicits{
implicit class RichInt(i: Int){
def complexCalculation: Int = 200*i // make this complex :)
}
}
object Algorithm{
var current = 1
def apply(rand: Random) = {
import MyImplicits._
current = rand.nextInt
current.complexCalculation + 100
}
}
// ImplicitSuite.scala in src/main/test
package implicittesting
import org.scalatest.FunSuite
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
@RunWith(classOf[JUnitRunner])
class DeleteSuite extends FunSuite {
import MyImplicits._
test("algorithm implicit class conversion test") {
assert(Algorithm(scala.util.Random) == Algorithm.current.complexCalculation + 200)
println(Algorithm.current)
}
}https://stackoverflow.com/questions/39126476
复制相似问题