首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >型富集Scala测试

型富集Scala测试
EN

Stack Overflow用户
提问于 2016-08-24 14:43:51
回答 4查看 688关注 0票数 11

例如,我开始依附于类型浓缩

代码语言:javascript
运行
复制
object MyImplicits{
  implicit class RichInt(i: Int){
    def complexCalculation: Int = i * 200 
  }
}

我在这样的代码中使用的

代码语言:javascript
运行
复制
object Algorithm{
  def apply(rand: Random) = {
    import MyImplicits._
    rand.nextInt.complexCalculation + 1
  }
}

但是我现在怎么能隔离和单元测试算法呢?特别是,我想嘲笑complexCalculation的实现,如下所示:

代码语言:javascript
运行
复制
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)
    }
  }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-09-02 06:35:05

当您有组合时,通常不需要模拟,因为您可以用实现来代替测试。尽管如此,在这种情况下,我并不是一个狂热的追求者,只是没有看到他们带来的价值。我会用旧的学校作文来解决这个问题(正如我在另一个评论中所暗示的):

代码语言:javascript
运行
复制
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来完成构图,您可以这样做:

代码语言:javascript
运行
复制
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

但是这不会给你一个计算的点语法。我的直觉也反对这种方法,因为这是定义行为的一种非常微妙的方法,而且很容易在所带来的重要意义上犯错误。

票数 2
EN

Stack Overflow用户

发布于 2016-08-31 04:22:23

RichInt.scala

代码语言:javascript
运行
复制
trait RichInt {
  def complexCalculation: Int
}

class RichIntImpl(i: Int) extends RichInt {
  def complexCalculation = i * 200
}

Algorithm.scala

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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
    }
  }
}
票数 1
EN

Stack Overflow用户

发布于 2016-08-24 15:29:54

下面使用的是最可缩放的api。模拟测试运行良好,隐式类转换正常。

代码语言:javascript
运行
复制
// 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)
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39126476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档