2013-04-03 4 views
11

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

То, что я хочу, чтобы случиться, что тест на хранилище без фактической передачи/подключения к реальной базе данных, я хочу это без использования каких-либо насмешек фреймворк.

В настоящее время мой тест отправляет данные в базу данных, что я хочу, чтобы проверить методы добавления/удаления и т. Д., Не отправляя фактические данные в базу данных, так как это только для тестирования.

Вот хранилище:

namespace AbstractFactory.Repository 
{ 
    using System.Collections.Generic; 
    using System.Data.Entity; 
    using System.Linq; 

    /// <summary> 
    /// This class serves as the structure of the Author repository using a database 
    /// </summary> 
    public class DbAuthorRepository : IRepository<AuthorEntity> 
    { 

     private AbstractFactoryPatternEntities context; 

     public DbAuthorRepository(AbstractFactoryPatternEntities context) 
     { 
      this.context = context; 
     } 

     /// <summary> 
     /// Adds the specified author. 
     /// </summary> 
     /// <param name="author">The author.</param> 
     public void Add(AuthorEntity author) 
     { 
      context.AuthorEntities.Add(author); 
     } 

     /// <summary> 
     /// Removes the specified author. 
     /// </summary> 
     /// <param name="author">The author.</param> 
     public void Remove(AuthorEntity author) 
     { 
      this.context.AuthorEntities.Remove(author); 
     } 

     /// <summary> 
     /// Saves this instance. 
     /// </summary> 
     public void Save() 
     { 
      this.context.SaveChanges(); 
     } 

     /// <summary> 
     /// Gets all. 
     /// </summary> 
     /// <returns>returns a list of all the authors</returns> 
     public IEnumerable<AuthorEntity> GetAll() 
     { 
      List<AuthorEntity> result = this.context.AuthorEntities.Include(a => a.Books).ToList(); 

      return result; 
     } 

     /// <summary> 
     /// Gets the author by id. 
     /// </summary> 
     /// <param name="id">The id.</param> 
     /// <returns>returns an entity</returns> 
     public AuthorEntity GetById(int id) 
     { 
      AuthorEntity result = this.context.AuthorEntities.Single(a => a.AuthorId == id); 

      return result; 
     } 
    } 
} 

Вот текущий код для модульного тестирования:

[TestMethod] 
     public void Add_MethodIsCalled_EntityCountIsIncrementedByOne() 
     { 
      using (ShimsContext.Create()) 
      { 
       ShimAbstractFactoryPatternEntities context = new ShimAbstractFactoryPatternEntities(new AbstractFactoryPatternEntities()); 
       DbAuthorRepository repository = new DbAuthorRepository(context); 
       repository.Add(new AuthorEntity { FirstName = "Test", LastName = "testing=" }); 
       var actual = repository.GetAll().Count(); 
       repository.Save(); 
       var expected = repository.GetAll().Count(); 
       Assert.AreNotEqual(actual, expected); 
      } 

      //AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities(); 
      //DbAuthorRepository repository = new DbAuthorRepository(context); 
      //var actual = repository.GetAll().Count(); 
      //repository.Add(new AuthorEntity { FirstName = "Testing", LastName = "MyTest" }); 
      //repository.Save(); 
      //var expected = repository.GetAll().Count(); 
      //Assert.AreNotEqual(actual, expected); 
     } 

     [TestMethod] 
     public void Remove_MethodIsCalled_EntityCountRemainsTheSame() 
     { 
      AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities(); 
      DbAuthorRepository repository = new DbAuthorRepository(context); 
      AuthorEntity newAuthor = new AuthorEntity { FirstName = "Testing", LastName = "MyTest" }; 
      repository.Add(newAuthor); 
      repository.Save(); 
      var actual = repository.GetAll().Count(); 
      Console.WriteLine(actual); 
      repository.Remove(newAuthor); 
      var expected = repository.GetAll().Count(); 
      Console.WriteLine(expected); 
      Assert.AreEqual(actual, expected); 
     } 

     [TestMethod] 
     public void Get_MethodIsCalled_CorrectAuthorIsRetrieved() 
     { 
      AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities(); 
      DbAuthorRepository repository = new DbAuthorRepository(context); 
      int target = 4; 
      AuthorEntity author = repository.GetById(target); 
      Assert.AreEqual(target, author.AuthorId); 
     } 

Я хочу использовать регулировочные шайбы/стаб/фальшивки для того, чтобы сделать тест.

+0

В чем вопрос? –

+1

Если все, что ваши репозитории делают, это одна строка кода, которая делает звонок в EF, вам не нужно вообще выполнять какие-либо модульные тесты. Даже дядя Боб соглашается: http://blog.8thlight.com/uncle-bob/2013/03/06/ThePragmaticsOfTDD.html – IronMan84

+0

+ 1 to @ IronMan84 - не пытайтесь протестировать любую фреймворк, иначе вы могли бы найти себе тестовый код, который вы не можете исправить. –

ответ

14

Репозиторий Entity Framework представляет собой конкретную реализацию вашего интерфейса репозитория. Поскольку это конкретное, вы не можете абстрагировать его и протестировать без базы данных - весь смысл этой конкретной реализации заключается в том, чтобы записать данные в базу данных!

Это означает, что тестирование репозиториев EF должно скорее нацеливаться на проверку того, что репозитории записываются в фактическую базу данных - на фазе действия вашего теста вы вызываете методы репозитория, а на этапе утверждения вы используете любой другой способ получения данных из базы данных (возможно, ado.net?), чтобы проверить, выполняет ли репозиторий свою работу.

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

+4

+1 Слишком много людей пытаются издеваться над чем-то, что не может насмехаться. Я собрал некоторые доказательства [здесь] (http://stackoverflow.com/a/13352779/861716). –

+0

@GertArnold: внушительные доказательства. –

+0

Если я понимаю, вы говорите, что нам нужно создать другую реализацию доступа к данным (используя ado.net), чтобы проверить работу EF. Разве это не слишком много накладных расходов? – betitall

5

Вы можете заменить подключение к базе данных с помощью встроенной памяти, например, «Усилия». Затем вы можете протестировать логику репозитория. Более подробную информацию можно найти: here

+3

Я думаю, что это должен быть комментарий, и это не ответ. –