I have lately become very interested in testing and Im now trying to learn to do unit testing in the best way possible. I use NUnit together with Rhino Mocks. I have also been reading a lot over here at Stackoverflow but havent been able to find a clear answer to my question.
What I wonder is if I have a method like the below, should I mock the OfficeClass dependency and also test GetAllOffices or only use a stub for the dependency and verify that the method GetAllOffices has been called and that I indeed get the offices back that I expected from my setup for the stub?
public Offices GetAllOffices()
{
try
{
var offices = officeClass.GetAllOffices();
return offices;
}
}
Will it make any difference if the OfficeClass is just another POCO or if it is let say a web service in sence of mocking vs stubbing?
Long question short: When to Mock and when to Stub in unit testing?
Mocks should be used when you want to test the order in which functions are called. Stubs verify the state of the system under test. Stubs don't take order into account, which can be helpful for reducing the work of rewriting tests when code is refactored.
Fakes are generally used to improve performance by avoiding external calls. Mocks are used to verify the behavior of our code. Stubs are used to provide data that our code needs to run. We should use the simplest test double that will get the job done.
A double is a general catch-all term for any sort of fake test object. In general, when you create any sort of test double, it's going to replicate an object of a specific class. A stub can be told to return a specified fake value when a given method is called.
Mocking is a very popular approach for handling dependencies while unit testing, but it comes at a cost. It is important to recognize these costs, so we can choose (carefully) when the benefits outweigh that cost and when they don't.
Mocks use a framework to generate a "mock" of your dependency. For example if officeClass is a repository for your data then you can use a mock framework (I use MOQ) to generate a mock of your repository. That's why using interfaces for your dependency make it ideal for testing, the mocking framework can easily make a mock of an interface for testing.
With stubs as I understand it, you manually stub out your dependency and create canned responses. For example if you have an interface IOfficeClass and you create a new class that inherits from it, you can inject that class into your service to allow you to use it.
Again things like web services should be wrapped in some interface (like the IRepository pattern), that will allow you to easily test your logic without needing to hit the web service. The same with POCO classes.
So for example in your case you would have:
public interface IOfficeRepository
{
IQueryable<Office> GetAll();
}
And for your service
public class MyOfficeService
{
private readonly IOfficeRepository officeRepostiory;
public MyOfficeService(IOfficeRepository repository)
{
this.officeRepostiory = repository;
}
public Office GetOffice(int id)
{
return this.officeRepostiory.GetAll().SingleOrDefault(o => o.Id == id);
}
}
This way you can also change your underlying datasource without having to modify your main application or business logic code.
Your unit test would look something like this using moq:
[TestClass]
public class OfficeUnitTest
{
private MyOfficeService service;
[TestInitialize]
public void Setup()
{
var officeRepository = new Mock<IOfficeRepository>();
var office = new List<Office>();
office.Add(new Office{ Id = 1 });
officeRepository.Setup(m => m.GetAll()).Returns(office.AsQueryable());
this.service = new MyOfficeService(officeRepository.Object);
}
[TestMethod]
public void TestGetById()
{
Assert.IsNotNull(service.GetOffice(1));
// my mock will never return a value for 2
Assert.IsNull(service.GetOffice(2));
}
}
You can read more about mocks and stubs below:
http://martinfowler.com/articles/mocksArentStubs.html
http://msdn.microsoft.com/en-us/library/ff649690.aspx
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