I have a fairly basic HomeController in my application and I wrote a test class for it. After running code coverage analysis on my test class I realized I don’t have any test for the default constructor.
This is my HomeController
public class HomeController : BaseController
{
private INewsRepository _newsRepository;
private INewsletterRepository _newsletterRepository;
private string _currentLanguage;
public HomeController()
{
_newsRepository = NewsRepository.Current;
_newsletterRepository = NewsletterRepository.Current;
_currentLanguage = ApplicationConfig.Current.CurrentLanguage;
}
public HomeController(INewsRepository newsRepository, INewsletterRepository newsletterRepository, string currentLanguage)
{
_newsRepository = newsRepository;
_newsletterRepository = newsletterRepository;
_currentLanguage = currentLanguage;
}
public ActionResult Index()
{
return View();
}
public ActionResult LatestNews()
{
return View(_newsRepository.ListAll().Where(n => n.LanguageKey.ToLower() == _currentLanguage.ToLower()).OrderByDescending(n => n.Date).Take(10));
}
public ActionResult LatestNewsletters()
{
return View(_newsletterRepository.ListAll().Where(n => n.LanguageKey.ToLower() == _currentLanguage.ToLower()).OrderByDescending(n => n.Date).Take(10));
}
}
And this is my test class for it:
[TestClass]
public class HomeControllerTest
{
private INewsletterRepository _mockNewsletterRepostiory = null;
private INewsRepository _mockNewsRepostiory = null;
private List<News> _fakeNewsList = new List<News> {
new News{Id = 0, Title = "some title", Date = new DateTime(1989, 2, 19), LanguageKey = "fa", Description = "some description"},
new News{Id = 1, Title = "some title", Date = new DateTime(1989, 2, 20), LanguageKey = "fa", Description = "some description"},
new News{Id = 2, Title = "some title", Date = new DateTime(1989, 2, 21), LanguageKey = "fa", Description = "some description"},
new News{Id = 3, Title = "some title", Date = new DateTime(1989, 2, 22), LanguageKey = "fa", Description = "some description"}
};
private List<Newsletter> _fakeNewsletterList = new List<Newsletter>
{
new Newsletter{ Id = 0, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 19) },
new Newsletter{ Id = 1, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 20) },
new Newsletter{ Id = 2, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 21) },
new Newsletter{ Id = 3, Description = "some description", UrlKey = "first-newsletter", Title = "some title", SendDate = null, NewsletterContents = null, LanguageKey = "fa", Date = new DateTime(1989, 2, 22) }
};
[TestInitialize]
public void Setup()
{
// Mock News Repository
var mockNewsRepository = MockRepository.GenerateStub<INewsRepository>();
mockNewsRepository.Stub(m => m.ListAll()).Return(_fakeNewsList.AsQueryable());
// Mock Newsletter Repository
var mockNewsletterRopository = MockRepository.GenerateStub<INewsletterRepository>();
mockNewsletterRopository.Stub(m => m.ListAll()).Return(_fakeNewsletterList.AsQueryable());
_mockNewsletterRepostiory = mockNewsletterRopository;
_mockNewsRepostiory = mockNewsRepository;
}
[TestMethod]
public void IndexReturnsView()
{
// Arrange
HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
// Act
ViewResult result = homeController.Index() as ViewResult;
// Assert
Assert.AreEqual("", result.ViewName);
}
[TestMethod]
public void LatestNewsReturnsCorrectObject()
{
// Arrange
HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
// Act
ViewResult result = homeController.LatestNews() as ViewResult;
// Assert
Assert.IsNotNull(result.ViewData.Model, "Result model is not null.");
Assert.IsTrue(_fakeNewsList.OrderByDescending(n => n.Date).SequenceEqual(result.ViewData.Model as IQueryable<News>), "Model is correct");
}
[TestMethod]
public void LatestNewslettersReturnsCorrectObject()
{
// Arrange
HomeController homeController = new HomeController(_mockNewsRepostiory, _mockNewsletterRepostiory, "fa");
// Act
ViewResult result = homeController.LatestNewsletters() as ViewResult;
// Assert
Assert.IsNotNull(result.ViewData.Model, "Result model is not null.");
Assert.IsTrue(_fakeNewsletterList.OrderByDescending(n => n.Date).SequenceEqual(result.ViewData.Model as IQueryable<Newsletter>), "Model is correct");
}
}
First of all do I really need to test this constructor?
Secondly, Is it a good practice to make the _newsRepository and the other guys public and readonly then write a test method to check their types after constructing the controller?
The only reason I’d recommend writing a test for the constructor is if you care a lot about getting as much code coverage as possible. Testing the fact that you can create an instance of the controller, and whether instances of each object created in the ctor are valid isn’t a very valuable test. I’d say it’s a waste of time.
So, for your first question I suggest you don’t worry about unit testing the ctor. If there is a problem in the ctor then you will notice it very quickly via other unit tests, as explained in my next comment.
As for making the repository classes public and readonly, I don’t recommend doing that. What you really need to focus on, regards unit tests, is functionality of the controller, especially methods that make use of the objects which are created in the ctor. That’s where you need to concentrate on. Those tests will tell you whether or not these was an issue in the ctor for those objects.