简体   繁体   中英

How can an IRepository be unit tested?

I have written the following method using the Repository mentioned in the following blog-post (http://www.codecapers.com/post/Using-RavenDB-with-ASPNET-MVC.aspx) using RavenDB:

public User GetUserById(string id)
{
     var user = (from usr in _repository.All<User>() where usr.Id == id select usr).FirstOrDefault();

     if (user == null)
     {
          throw new NullReferenceException("No user with the id (" + id + ") could be found.");
     }

     return user;
}

How would you unit test this method with nunit (and perhaps moq)?

"user" is just a normal class.

Usualy you don't write tests directly against the repository layer. Say for example you are using nHibernate or Entity Framework, than wirting tests against the repository would technically be testing that framework.

The creators or those ORMs already done that.

Also talking to a database makes your test an integration test not a unit test.

Your unit test would be for example against the business layer mocking out the repository layer.

If you want to write an integration test you also write that against the business layer but don't mock the repository layer and let it go through.

I would do the following to prepare your code:

  1. Make sure your _repository is being passed in through a constructor or property, so that it can be easily changed for tests.
  2. Make sure your _repository variable is declared as the IRepository type, rather than the concrete type.

Then, in your tests:

  1. Create a mock of your interface and pass this in to be your _repository .
  2. Override the .All<User>() method to return a known, hardcoded list of User with suitable values for your tests.
  3. Assert in one test that the correct value is returned when you query an existing ID.
  4. Assert in a separate test that the exception is thrown when you query a non-existant ID.

The first question is going to be - what are you testing in this context? The method provided really only has two outcomes, so you're basically testing whether user is null or not. Is that a value added test?

As for the how , Im assuming _repository is injected via some mechanism? If so, then you simply provide a Mock<IRepository> (insert your type name as appropriate) and inject that in the place of _repository wherever that is injected. Then you can setup the return values and test your method for the exception or not.

mockRepository.Setup(x => x.All<User>()).Returns(new List<User> { ... });

RavenDB is specifically designed so that you don't need to mock everything for unit testing.

Just run it in-memory and you can then perform you unit tests against it directly. See this blog post for more info.

It lets you write code like this:

[Fact]
public void CanQueryForDistinctItemsUsingLinq()
{
    using (var store = NewDocumentStore())
    {
        using (var s = store.OpenSession())
        {
            s.Store(new { Name = "ayende" });
            s.Store(new { Name = "ayende" });
            s.Store(new { Name = "rahien" });
            s.SaveChanges();
        }

        store.DocumentDatabase.PutIndex("test", new IndexDefinition
        {
            Map = "from doc in docs select new { doc.Name }",
            Stores = { { "Name", FieldStorage.Yes } }
        });

        using (var s = store.OpenSession())
        {
            var objects = s.Query<User>("test")
                .Customize(x => x.WaitForNonStaleResults())
                .Select(o => new {o.Name })
                .Distinct()
                .ToList();

            Assert.Equal(2, objects.Count);
            Assert.Equal("ayende", objects[0].Name);
            Assert.Equal("rahien", objects[1].Name);
        }
    }
}

This comes from RavenDB unit/integration tests , so you'll need some infasctucture to get it working, but it gives the general idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM