I'm trying to test an Order entity method called AddItem and I'm trying to make sure that duplicate items cannot be added. Here is some example code:
[Test]
public void ItemCannotBeAddedTwiceToOrder()
{
Order o = new Order();
Item i = new Item("Bike");
o.AddItem(i);
o.AddItem(i);
Assert.AreEqual(o.ItemCount, 1, "A duplicate item was added.");
}
public void AddItem(Item newItem)
{
if(!CheckForDuplicateItem(newItem))
_items.Add(newItem);
}
public bool CheckForDuplicateItem(Item newItem)
{
foreach(Item i in _items)
{
if(i.Id == newItem.Id)
return true;
}
return false;
}
So here is my problem: how do I set the new Item's private setter Id in the test method so the CheckForDuplicateItem method will work? I don't want to make that member public for good coding practices, I guess. Am I just being stupid and need to make the entity Item have a public Id setter? Or do I need to use reflection? Thanks
Note - I'm using NHibernate for persistence
Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods aren't aware of. Furthermore, changing our implementation details shouldn't lead us to change our tests.
Use the TestVisible annotation to allow test methods to access private or protected members of another class outside the test class. These members include methods, member variables, and inner classes. This annotation enables a more permissive access level for running tests only.
The unit test should only test the public interface. Each private method is an implementation detail. They contain the logic necessary to implement a piece of functionality. Private methods exist due to code reusability and to avoid having large public methods that do everything.
I would say don't write unit tests for setters and getters, unless your setters and getters contain program logic (something getting computed as the setter or getter is called). On a real project you will have more than plenty program logic to unit test without having to test something trivial like setters and getters.
I usually use reflection for this purpose. Something like this will work:
typeof(Item).GetProperty(nameof(Item.Id)).SetValue(i, 1, null);
where 1 is the id that you want to set for the newItem instance.
In my experience, you'll rarely need to set the Id, so it's better just to leave the setter private. In the few cases that you do need to set the Id for testing purposes, simply use Reflection.
Since you are checking the behavior of your Order you can use mock objects as its items. Using mock objects you can define your assertions of what's going to happen to your mock objects and test them too. In this case you can define two mock objects for each of items and expect that their id getter will be called and will return a unique value.Then you can test the Order behavior and check to see if id getter of item is called as you expected. I recommend using Rhino Mocks by Ayende
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