This is my first question so please be kind! :)
What I am trying to do is write some tests for a manager class that during construction adds many new instances of a single item class to a list. When the UpdateAllItems is called in this manager class the intention is to iterate the list and call Increment on each single item.
The manager class is my code, but the single item class is not so I can't modify it.
I use NUnit for a testing framework and am starting to work with Moq. Because the manager class uses the single item class I would think I need to use a Moq so I am testing only the manager, not the single item.
How do I write tests for my UpdateAllItems method? (Technically I should be writing the tests first I know).
Here is a some sample code that gives a general idea of what I am working with...
public class SingleItem_CodeCantBeModified
{
public int CurrentValue { get; private set; }
public SingleItem_CodeCantBeModified(int startValue)
{
CurrentValue = startValue;
}
public void Increment()
{
CurrentValue++;
}
}
public class SingleItemManager
{
List<SingleItem_CodeCantBeModified> items = new List<SingleItem_CodeCantBeModified>();
public SingleItemManager()
{
items.Add(new SingleItem_CodeCantBeModified(100));
items.Add(new SingleItem_CodeCantBeModified(200));
}
public void UpdateAllItems()
{
items.ForEach(item => item.Increment());
}
}
Thanks in advance for all the help!
Moq supports mocking protected methods. Changing the methods to protected , instead of private , would allow you to mock their implementation.
You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces. However, there are a few limitations you should be aware of. The classes to be mocked can't be static or sealed, and the method being mocked should be marked as virtual.
Unit testing is a powerful way to ensure that your code works as intended. It's a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation. Moq is a mock object framework for .
The simple answer is, you can't. The method that UpdateAllItems
calls (Increment()
) is non-virtual, so you won't be able to mock it.
Your options, as I see it, are:
UpdateAllItems
at all. Its implementation is trivial, so this is an option to consider (though not ideal).SingleItem_CodeCantBeModified
instances in your test. Purists would say that you no longer have a unit test at this point, but it could still be a useful test.ISingleItem
interface, and an SingleItemAdapter : ISingleItem
class that holds onto a reference to a SingleItem_CodeCantBeModified
and forwards the calls. Then you can write SingleItemManager
to operate on ISingleItem
s, and you'll be free to pass in mock ISingleItem
s in your tests. (Depending on how your system is set up, you might even be able to descend from SingleItem_CodeCantBeModified
, implement the interface on your descendant, and use those objects instead of writing an adapter.)That last option gives you the most options, but at the cost of some complexity. Choose the option that's best suited for what you're trying to accomplish.
Your Manager is too dependent on Item (in List<Item>
). Can you extract list population into separate class to be able to mock it? e.g.:
public SingleItemManager()
{
items.Add(ItemRepository.Get(100));
items.Add(ItemRepository.Get(200));
}
Testing (some code omitted):
int i = 0;
var itemMock = new Mock<Item>();
itemMock.Setup(i => i.Increment()).Callback(() => i++);
var repositoryMock = new Moc<ItemRepository>();
repositoryMock.Setup(r => r.Get(It.IsAny<int>()).Returns(itemMock.Object);
var manager = new SingleItemManager();
manager.UpdateAllItems();
Assert.AreEqual(i, 1);
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