In my C# unit tests, I often query for a list of rows based on a list of IDs. I then want to ensure that 1) for all the IDs, there was at least one row found that has that ID and 2) for all the returned rows, each row has an ID that is in the list of IDs to find. Here is how I usually ensure that:
Assert.IsTrue(ids.All(
id => results.Any(result => result[primaryKey].Equals(id))
), "Not all IDs were found in returned results");
Assert.IsTrue(results.All(
result => ids.Any(id => result[primaryKey].Equals(id))
), "Returned results had unexpected IDs");
I think the use of Any
and All
is convenient for such checks, but I wanted to see if anyone thinks this is less readable than it could be, or if there is perhaps a nicer way of doing two-way checks like this. I'm using MSTest in Visual Studio 2008 Team System for unit testing. This perhaps should be community wiki if it's too subjective.
Edit: I'm now using a solution based on Aviad P.'s suggestion, and also the fact that the following test passes:
string[] ids1 = { "a", "b", "c" };
string[] ids2 = { "b", "c", "d", "e" };
string[] ids3 = { "c", "a", "b" };
Assert.AreEqual(
1,
ids1.Except(ids2).Count()
);
Assert.AreEqual(
2,
ids2.Except(ids1).Count()
);
Assert.AreEqual(
0,
ids1.Except(ids3).Count()
);
You might choose to use the Except
operator:
var resultIds = results.Select(x => x[primaryKey]);
Assert.IsTrue(resultIds.Except(ids).Count() == 0,
"Returned results had unexpected IDs");
Assert.IsTrue(ids.Except(resultIds).Count() == 0,
"Not all IDs were found in returned results");
IMO, not as readable as it could be. Create and document a method which returns true / false. Then call Assert.IsTrue(methodWithDescriptiveNameWhichReturnsTrueOrfalse(), "reason for failure");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With