So I am creating a Scala UnitTest using ScalaTest/ScalaCheck for a local cache implementation, and I need to test the functionality that if an event comes in with an ID we have already seen, it updates that value instead of creating a whole new entry in the cache.
I'm now sure how to do this so that the same id is generated for each iteration of the loop. See code below.
forAll { arbitraryEvent: ClientFacingExecution =>
val unmatchedEvent = ClientFacingExecutionEnriched(arbitraryFoExec)
val expectedId = unmatchedEvent.clientFacingExecution.id
........................................
........................................
........................................
cacheUnderTest.records should have size 1
}
How can I ensure that expectedId will always be the same while the rest of the unmatchedEvent will be regenerated.
Since I do not know the full definition of your class ClientFacingExecution, consider an analogous case class Record defined as
case class Record(id: Int, str: String)
To create a generator for a case class such as Record with a fixed id, for example,
val someId = 1
val simpleRecordGenerator:Gen[Record] = Gen.resultOf(Record).map(_.copy(id = someId))
This approach will ensure the id is fixed and may work for you, but it lacks flexibility should you want to generate other fields of your class. A slightly more sophisticated and flexible approach allows you to combine generators in new ways.
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
}
Here we supply the generator as the first argument to forAll. The second argument to forAll is a function that accepts a generated value from the generator supplied as the first argument.
The zip method, sometimes called a combinator, combines generators. In this case we combine a generator for an arbitrary record where the id could be any value from Integer.MIN_VALUE to Integer.MAX_VALUE and then overwrite that value is a more constrained value with Gen.const. This construct is flexible in that you can use to constrain values in others ways if you choose without drastically changing the code, say by using Gen.choose(0,100) in place of Gen.const to generate arbitrary ids in the range of 0 to 100.