Effects Of Encapsulation On Unit Tests – EnumerableAssert
To keep your classes properly encapsulated, I’ve learned (from others and my
own experience) that it’s usually a good idea to expose collections only as
IEnumerable
keeping with this, it can sometimes make your unit tests less elegant. Here are
some examples and a quick little helper that can make things more
readable…
So an extremely simple example would be something like this.
[Test]
public void Should_add_item_to_basket()
{
IBasket basket = new Basket();
IBasketItem basketItem = new BasketItem();
basket.AddItemToBasket(basketItem);
// TODO: Assert that the item was added to the basket
}
For reference, here is the IBasket interface:
public interface IBasket
{
IEnumerable<IBasketItem> Items { get; }
void AddItemToBasket(IBasketItem itemToAdd);
}
Ok, so of course there are a number of ways we could write this assertion.
Here are a couple examples using the out of the box MbUnit assertions.
Assert.IsTrue(new List<IBasketItem>(basket.Items).Contains(basketItem));
CollectionAssert.Contains(new List<IBasketItem>(basket.Items), basketItem);
foreach (IBasketItem currentItem in basket.Items) Assert.AreEqual(currentItem, basketItem);
Don’t know about you, but those seem a little too verbose to me. I tend to
like something like this better.
EnumerableAssert.Contains(basket.Items, basketItem);
But you won’t find that in the MbUnit framework. Fortunately it’s easy
enough to write a little wrapper to “hide” the verbosity.
public class EnumerableAssert
{
public static void Contains<T>(IEnumerable<T> enumerable, T actual)
{
CollectionAssert.Contains(new List<T>(enumerable), actual);
}
}
Notice all I’m doing is leveraging one of MbUnit’s existing assertions
(CollectionAssert) to wrap an IEnumerable
assertion. Pretty simple stuff, but it can help keep your tests more
readable.