Шаблон хранилища и модульное тестирование из памяти

Я видел некоторые реализации шаблона репозитория, очень простую и интуитивную, связанную форму других ответов здесь, в 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>();
    }
...

Как я могу настроить его на работу из памяти при выполнении модульного тестирования? Есть ли способ построить таблицу DataContext или Linq из чего-либо в памяти? Моя идея состояла в том, чтобы создать коллекцию (List, Dictionary...) и заглушить ее при модульном тестировании.

Спасибо!

EDIT: Мне нужно что-то вроде этого:

  • У меня есть классная книга
  • У меня есть библиотека классов
  • В конструкторе Library я инициализирую репозиторий:

    var bookRepository = new Repository<Book>(dataContext)

  • И методы Library используют репозиторий, как этот

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

При тестировании я хочу предоставить контекст памяти. Когда я буду в производстве, я дам реальный контекст базы данных.

Ответ 1

Я предлагаю использовать насмешливую библиотеку, например Moq или RhinoMocks. Хороший учебник с использованием Moq можно найти здесь.

Прежде чем вы решите, какой из них вы будете использовать, следующие действия могут помочь:

Дополнительная информация. Сравнение unit test рамки можно найти здесь.


ОБНОВЛЕНИЕ после запроса OP

Создать базу данных в памяти

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

Мокайте свой репозиторий (я использовал Moq для следующего примера)

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

Настройте свой репозиторий

// 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));

Создайте объект библиотеки, передав свой макет объекта в параметре конструктора

var library = new Library(repository.Object);

И, наконец, некоторые тесты:

// 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
.....