Repository Pattern and unit testing from memory

27,077

I'd suggest to use a mocking library like Moq or RhinoMocks. A nice tutorial using Moq can be found here.

Before you decide which one you'll use, the followings might help:

Additional information : Comparison of unit test framework can be found here.


UPDATE following OP's request

Create a in memory database

var bookInMemoryDatabase = new List<Book>
{
    new Book() {Id = 1, Name = "Book1"},
    new Book() {Id = 2, Name = "Book2"},
    new Book() {Id = 3, Name = "Book3"}
};

Mock your repository (I used Moq for the following example)

var repository = new Mock<IRepository<Book>>();

Set up your repository

// When I call GetById method defined in my IRepository contract, the moq will try to find
// matching element in my memory database and return it.

repository.Setup(x => x.GetById(It.IsAny<int>()))
          .Returns((int i) => bookInMemoryDatabase.Single(bo => bo.Id == i));

Create a library object by passing your mock object in constructor parameter

var library = new Library(repository.Object);

And finally some tests :

// First scenario look up for some book that really exists 
var bookThatExists = library.GetByID(3);
Assert.IsNotNull(bookThatExists);
Assert.AreEqual(bookThatExists.Id, 3);
Assert.AreEqual(bookThatExists.Name, "Book3");

// Second scenario look for some book that does not exist 
//(I don't have any book in my memory database with Id = 5 

Assert.That(() => library.GetByID(5),
                   Throws.Exception
                         .TypeOf<InvalidOperationException>());

// Add more test case depending on your business context
.....
Share:
27,077

Related videos on Youtube

Kaikus
Author by

Kaikus

Updated on July 09, 2022

Comments

  • Kaikus
    Kaikus almost 2 years

    I have seen some implementations of the Repository Pattern, very simple and intuitive, linked form other answers here in stackoverflow

    http://www.codeproject.com/Tips/309753/Repository-Pattern-with-Entity-Framework-4-1-and-C http://www.remondo.net/repository-pattern-example-csharp/

    public interface IRepository<T>
    {
        void Insert(T entity);
        void Delete(T entity);
        IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
        IQueryable<T> GetAll();
        T GetById(int id);
    }
    
    public class Repository<T> : IRepository<T> where T : class, IEntity
    {
        protected Table<T> DataTable;
    
        public Repository(DataContext dataContext)
        {
            DataTable = dataContext.GetTable<T>();
        }
    ...
    

    How can I set it to work from memory when doing unit testing? Is there any way to build a DataContext or Linq Table from anything in memory? My idea was to create a collection (List, Dictionary...) and stub it when unit testing.

    Thanks!

    EDIT: What I need something like this:

    • I have a class Book
    • I have a class Library
    • In the Library constructor, I initialize the repository:

      var bookRepository = new Repository<Book>(dataContext)

    • And the Library methods use the repository, like this

      public Book GetByID(int bookID)
      { 
          return bookRepository.GetByID(bookID)
      }
      

    When testing, I want to provide a memory context. When in production, I will provide a real database context.

    • Mechanical Object
      Mechanical Object over 10 years
      I added some sample code following your request.
  • Kaikus
    Kaikus over 10 years
    Many thanks for the tutorial!. But I need to test an existing class that is using the repository. Creating a 'fake' repository and testing it this way only serves me to test that the repository pattern is well implemented. I'll try to clarify my question by editing it
  • Mechanical Object
    Mechanical Object over 10 years
    @Kaikus : If you can give brief implementation of the class using repository it would be helpful
  • Kaikus
    Kaikus over 10 years
    So, If I understand correctly, the idea is not to stub the 'context', but to mock completely the repository. Then when instantiate a entity, I allways must inject its own repository (the real one or the mock one) using the constructor. Thanks!