使用ScalaCheck forAll,如何设置case类的一个参数并让其余参数随意生成?

问题描述 投票:0回答:1

所以我使用ScalaTest / ScalaCheck创建一个Scala UnitTest用于本地缓存实现,我需要测试一个功能,如果一个事件带有我们已经看过的ID,它会更新该值而不是创建一个全新的条目缓存。

我现在确定如何做到这一点,以便为循环的每次迭代生成相同的id。见下面的代码。

forAll { arbitraryEvent: ClientFacingExecution =>
      val unmatchedEvent = ClientFacingExecutionEnriched(arbitraryFoExec)
      val expectedId = unmatchedEvent.clientFacingExecution.id

      ........................................
      ........................................
      ........................................

      cacheUnderTest.records should have size 1
}

如何在重新生成unmatchedEvent的其余部分时确保expectedId始终相同。

scala unit-testing scalatest scalacheck
1个回答
1
投票

由于我不知道您的类ClientFacingExecution的完整定义,请考虑定义为类似的案例类Record

case class Record(id: Int, str: String)

例如,为案例类创建生成器,例如具有固定id的Record

val someId = 1
val simpleRecordGenerator:Gen[Record] = Gen.resultOf(Record).map(_.copy(id = someId))

这种方法将确保id已修复并可能适合您,但如果您想生成类的其他字段,则它缺乏灵活性。稍微复杂和灵活的方法允许您以新的方式组合发电机。

val someId = 1
val recordGenerator:Gen[Record] = Gen.zip(Gen.resultOf(Record), Gen.const(someId)).map{ case (record, id) => record.copy(id = id) }

forall(recordGenerator){ record: Record => 
...
cacheUnderTest.records should have size 1
} 

这里我们提供生成器作为forAll的第一个参数。 forAll的第二个参数是一个函数,它接受来自作为第一个参数提供的生成器的生成值。

zip方法(有时称为组合器)结合了生成器。在这种情况下,我们将一个生成器组合成一个任意记录,其中id可以是从Integer.MIN_VALUE到Integer.MAX_VALUE的任何值,然后使用Gen.const覆盖该值是一个更受约束的值。这个结构很灵活,你可以用它来以其他方式约束值,如果你选择没有大幅改变代码,比如使用Gen.choose(0,100)代替Gen.const来生成0到100范围内的任意id 。

© www.soinside.com 2019 - 2024. All rights reserved.