atrium icon indicating copy to clipboard operation
atrium copied to clipboard

Iterator.toHaveNext/notToHaveNext change depending on side effects of the underlying iterator

Open robstoll opened this issue 1 year ago • 0 comments

Affected Version

1.2.0

API

fluent, infix

Platform

jvm, js

Kotlin Version

1.9.24 (api verison 1.4)

How to reproduce the problem?

expect(listOf(1).iterator()) {
  toHaveNext() // holds, however the test behind is recomputed on next`holds()` call
  feature { f(it::next()) }.toEqual(1) // holds as well but now the toHaveNext before doesn't hold any more because it is recalculated
  notToHaveNext()
}

I guess we have the same problem in IterableLikeAssertion.toHaveNext/notToHaveNext in case the Iterable can only be consumed once.

Describe the bug

We could have the same problem elsewhere as well. The problem at hand, is with the way we try to calculate holds lazily. It would not be enough to store the result in DescriptiveAssertion in case another assertion does not calculate lazily but eagerly. E.g. if feature { f(it::next()) } calculates eagerly and thus before the toHaveNext calculates, then we would still have an ordering problem. Also imagine feature is calculated lazily (which I think is actually the case) but notToHave is not, then we still would get wrong results.

Expected behaviour

In the end I expect that the above shown code holds, i.e. that the side effect of next affects notToHaveNext which follows but does not affect toHaveNext which was earlier.

robstoll avatar May 25 '24 13:05 robstoll