I'm trying to do a test on my controllers which get data from repository classes. This is the part of the repository I want to test:
public class NewsRepository
{
public IEnumerable<NewsItem> GetNews()
{
var result = (from n in n_db.NewsItems
orderby n.ID descending
select n).Take(3);
return result;
}
}
Just some small code to get how the testing works. In my HomeController I've got this code inside the Index():
public ActionResult Index()
{
ViewBag.Message = "Announcements";
NewsRepository n_rep = new NewsRepository();
var model = i_rep.GetNews();
return View(model);
}
I am completely new to testing so all explanations would be great. Thanks.
Unit testing can be done manually but is usually automated. Unit testing is a part of the test-driven development (TDD) methodology that requires developers to first write failing unit tests. Then they write code in order to change the application until the test passes.
To run all the tests in a default group, choose the Run icon and then choose the group on the menu. Select the individual tests that you want to run, open the right-click menu for a selected test and then choose Run Selected Tests (or press Ctrl + R, T).
Your controller is impossible to be unit tested in isolation because it is strongly coupled with your repository on the following line:
NewsRepository n_rep = new NewsRepository();
You have simply hardcoded a specific implementation of the repository and in your unit test you cannot mock it. In order to do this properly you should start by defining an abstraction over this repository:
public interface INewsRepository
{
IEnumerable<NewsItem> GetNews();
}
and then have your specific repository implement this interface:
public class NewsRepository : INewsRepository
{
...
}
Ok now that we have an abstraction let's weaken the coupling between your data access and controller logic by using this abstraction:
public class NewsController: Controller
{
private readonly INewsRepository repository;
public NewsController(INewsRepository repository)
{
this.repository = repository;
}
public ActionResult Index()
{
ViewBag.Message = "Announcements";
var model = this.repository.GetNews();
return View(model);
}
}
Alright, now you have a controller that is no longer tightly coupled with some specific implementation. You could pickup your favorite mock framework and write a unit test. For example with NSubstitute
here's how the unit test for the Index action might look like:
[TestMethod]
public void Index_Action_Fetches_Model_From_Repo()
{
// arrange
var repo = Substitute.For<INewsRepository>();
IEnumerable<NewsItem> expectedNews = new[] { new NewsItem() };
repo.GetNews().Returns(expectedNews);
var sut = new NewsController(repo);
// act
var actual = sut.Index();
// assert
Assert.IsInstanceOfType(actual, typeof(ViewResult));
var viewResult = actual as ViewResult;
Assert.AreEqual(expectedNews, viewResult.Model);
}
And that's pretty much it. Your controller is now easily unit testable in isolation. You don't need to be setting up databases or whatever. That's not the point to test the controller logic.
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