Brendan Vogt
Brendan Vogt

Reputation: 26038

Help/advice needed with unit testing repositories

I am using .NET 4, NUnit and Rhino mocks. I want to unit test my news repository, but I am not sure of how to go about it. My news repository is what I will eventually be using to communicate to the database. I want to use it to test against fake/dummy data. Not sure if it is possible?? This is what I currently have:

public interface INewsRepository
{
   IEnumerable<News> FindAll();
}

public class NewsRepository : INewsRepository
{
   private readonly INewsRepository newsRepository;

   public NewsRepository(INewsRepository newsRepository)
   {
      this.newsRepository = newsRepository;
   }

   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

My unit test looks like this:

public class NewsRepositoryTest
{
   private INewsRepository newsRepository;

   [SetUp]
   public void Init()
   {
      newsRepository = MockRepository.GenerateMock<NewsRepository>();
   }

   [Test]
   public void FindAll_should_return_correct_news()
   {
      // Arrange
      List<News> newsList = new List<News>();
      newsList.Add(new News { Id = 1, Title = "Test Title 1" });
      newsList.Add(new News { Id = 2, Title = "Test Title 2" });

      newsRepository.Stub(r => r.FindAll()).Return(newsList);

      // Act
      var actual = newsRepository.FindAll();

      // Assert
      Assert.AreEqual(2, actual.Count());
   }
}

In the above code I am not sure what I need to mock. The code above compiles but fails in the NUnit GUI about a contructor value. I can only assume it has to do with the INewsRepository paramter that I need to supply to NewsRepository. I don't know how to do this in the test. Can someone please rectify my unit test so that it will pass in the NUnit GUI? Can someone also provide some feedback on if I am implementing my repositories correctly?

Being a newbie to mocking, is there anything that I need to verify? When would I need to verify? What is its purpose? I have been working through a couple of source code projects and some use verify and some don't.

If the above test passes, what does this prove to me as developer? What does another developer have to do to my repository to make it fail in the NUnit GUI?

Sorry for all the questions, but they are newbie questions :)

I hope soomeone can help me out.

Upvotes: 2

Views: 3720

Answers (3)

Steven
Steven

Reputation: 172776

Your FindAll_should_return_correct_news test method is not testing the repository, it is testing itself. You can see this when you simplify it to what it really does:

[Test]
public void FindAll_should_return_correct_news()
{
   // Arrange
   List<News> newsList = new List<News>();
   newsList.Add(new News { Id = 1, Title = "Test Title 1" });
   newsList.Add(new News { Id = 2, Title = "Test Title 2" });

   // Act
   var actual = newsList;

   // Assert
   Assert.AreEqual(2, actual.Count());
}

As you can see, what you're basically doing is creating a list, filling it and testing if it actually contains the number of records that you put in it.

When your repository does nothing else than database interaction (so no application logic) there is nothing to test using a unit test. You can solve this problem by writing integration tests for the repositories. What you can basically do with such a integration test is insert some records in a test database (use a real database though, not an in-memory database) and then call the real repository class to see if it fetches the expected records from your test database. All should be executed within a transaction and rolled back at the end of the test (this ensures these tests keep trustworthy).

When you're using a O/RM tool that allows you to write LINQ queries, you could also try a different approach. You can fake your LINQ provider, as you can see in this article.

Upvotes: 2

StuperUser
StuperUser

Reputation: 10850

As Steven has said, you're Asserting against the Mock NewsRepository in the above code.

The idea of mocking is to isolate the Code Under Test and to create fakes to replace their dependencies.

You use the Mock NewsRepository to test something that uses INewsRepository, in your case, you mention NewsService; NewsService will use your mock of INewsRepository.

If you search your solution for anything that uses INewsRepository.FindAll(), you will create a Mock Repository to test that code in isolation.

If you want to test something that calls your Service layer, you will need to mock NewsService.

Also, as Steven as said, there is no need for the NewsRepository to have a copy of itself injected by IoC, so:

public class NewsRepository : INewsRepository
{
   private readonly INewsRepository newsRepository;

   public NewsRepository(INewsRepository newsRepository)
   {
      this.newsRepository = newsRepository;
   }

   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

should become:

public class NewsRepository : INewsRepository
{
   public IEnumerable<News> FindAll()
   {
      return null;
   }
}

Once you have functionality in your FindAll() method that needs testing, you can mock the objects that they use.

As a point of style from the great Art Of Unit Testing initialisation of mock objects is best left out of the Setup method and carried out in a helper method called at the start of the method. Since the call to Setup will be invisible and makes the initalisation of the mock unclear.

As another point of style, from that book, a suggested unit test naming convention is: "MethodUnderTest_Scenario_ExpectedBehavior". So,

FindAll_should_return_correct_news
could become, for example:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2

I hope this makes the approach clearer.

Upvotes: 5

BlackICE
BlackICE

Reputation: 8926

Might want to read over this post by ayende

Upvotes: 1

Related Questions