ScalaTest与模拟对象

问题描述

我找到了一些简单的例子,但是没有用。

模型:

class Product() {
  var price: Int = 0
  var stock: Int = 0

  def addPrice(price: Int): Int = {
    this.price = price
    this.price
  }

  def addStock(qty: Int): Int = {
    this.stock += qty
    this.stock
  }
}

和我的考试班

classproductSpec extends AnyFlatSpec with MockFactory with OneInstancePerTest {
  val m = mock[Product]

  // suites (test examples)
  inAnyOrder {
   (m.addPrice _).expects(40).returns(40).once
   inSequence {
     (m.addStock _).expects(20).returns(20).once
     (m.addStock _).expects(10).returns(30).once
   }
  }

  // tests
  it should "set price" in {
    assert(m.addPrice(40) == 40)
  }

  it should "add new qty. Step 1" in {
    assert(m.addStock(20) == 20)
  }

  it should "add new qty. Step 2" in {
    assert(m.addStock(10) == 30)
  }
}

每次,错误是:

Expected:
  inAnyOrder {
     inAnyOrder {
     <mock-1> Product.addPrice(40) once (never called - UNSATISFIED)
    ...
  }
}

如果我只运行一个套件和一个断言,它将起作用:

(m.addPrice _).expects(40).returns(40).once
// tests
it should "set price" in {
  assert(m.addPrice(40) == 40)
}

解决方法

让我们解释上面的代码。 inAnyOrder部分为所有测试定义断言。这意味着,在套件中的每个测试中,您应该只调用一次:

  1. m.addPrice(40)
  2. m.addStock(20)
  3. m.addStock(10)

而2必须在3之前。因此,每个测试由于缺少2个调用而失败。例如,测试:

it should "add new qty. Step 1" in {
  assert(m.addStock(20) == 20)
}

失败,并显示以下消息:

Expected:
inAnyOrder {
inAnyOrder {
    <mock-1> Product.addPrice(40) once (never called - UNSATISFIED)
    inSequence {
    <mock-1> Product.addStock(20) once (called once)
    <mock-1> Product.addStock(10) once (never called - UNSATISFIED)
    }
}
}

Actual:
<mock-1> Product.addStock(20)
ScalaTestFailureLocation: ProductSpec at (ProductSpec.scala:20)
org.scalatest.exceptions.TestFailedException: Unsatisfied expectation:

因为1和3不满意。

如果您尝试像这样的测试:

it should "set price" in {
  assert(m.addPrice(40) == 40)
  assert(m.addStock(20) == 20)
  assert(m.addStock(10) == 30)
}

它将通过。 请注意,如果您更改2和3的顺序,则相同的测试将失败。