views:

418

answers:

4

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

+4  A: 

I usually use reflection for this purpose. Something like this will work:

typeof(Item).GetProperty("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.

Praveen Angyan
Thanks a lot. I'll give this a try.
CalebHC
+6  A: 

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

Beatles1692
Good point. I'll look into mocking. I've heard a lot of good things about Rhino Mocks.
CalebHC
A: 

Another solution is to make private members accessible by deriving from the class and exposing the member in the derived class. This is quite a lot overhead for testing and Visual Studio has only build-in support for private methods.

Daniel Brückner
A: 

I think you might be missing the point here. Are you avoiding multiple additions because you don't want multiple calls to the DB? I think NHibernate gives you that for free. Alternatively, should you be using a Set? What are the implications for the caller that an item might or might not be added?

If there's no persistence issue, you could just add two distinct items with the same ID and confirm that you only have the first one. There must be some way of detecting which items are in the order, or there would be no point in adding them...

Steve Freeman