Is it ok to add deferred assertions like this [..]
No, it isn't. Why? Because if you for any reason remove the second assert the test would still turn green and you would think it still works but it doesn't as the collection won't get enumeratated. If you have two or more independent assertions they'll keep doing their job even if you disable one of them.
Consider this combination:
Assert.IsTrue(actualKittens.All(x => x.IsCute());
CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());
Now even if you disable or remove one of the asserts the other one would still do its job. Also if you forget to materialize the collection it might take longer to run but it'll still be working. Independent tests are more robust and reliable.
There is also a second no. I'm not sure how other frameworks handle it but if you are using MS Test platform then you wouldn't know which test failed. If you double click the failed test it'll show you the CollectionAssert
as failed but in reality it was the nested Assert
that went wrong and it'll be extremely hard to debug. Here's an example:
[TestMethod]
public void TestMethod()
{
var numbers = new[] { 1, 2, 3 }.Select(x =>
{
Assert.Fail("Wrong number.");
return x;
});
// This will fail and you won't be sure why.
CollectionAssert.AreEqual(new[] { 1, 2, 3 }, numbers.ToList());
}
This means that the first test is actually useless because it doesn't help to find a bug. You don't know whether it failed because a number was invalid or because both collections were different.
Why? So I can iterate just once even with statements expecting materialized collection
I wonder why you care about it? These are unit tests. You don't have to optimize every bit of them and usually tests do not require millions of items so performance should not be a concern.
You'll need to maintain such tests so why should you make them more complex then necessary? Write simple asserts that work.