2016-08-03 6 views
0

Я нашел несколько примеров, которые показывают (по-видимому) ясный рабочий пример издевательского DbContext с EF 6, однако ни один из них не работает для меня, и я не совсем понимаю, почему.Mocking DbContext в Entity Framework 6.1

Это мой модульный тестовый код, который устанавливает макет;

var mockData = new List<User> { new User { Email = "[email protected]", Id = 1 } }.AsQueryable(); 

var mockSet = new Mock<DbSet<User>>(); 
    mockSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(mockData.Provider); 
    mockSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(mockData.Expression); 
    mockSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(mockData.ElementType); 
    mockSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(mockData.GetEnumerator()); 

    var mockContext = new Mock<MyDbContext>(); 
    mockContext.Setup(c => c.Users).Returns(mockSet.Object); 

, а затем вызов службы, которую я тестирую;

var service = new UsersService(mockContext.Object); 

var user = service.GetById(1); 

Это генерирует исключение NullReferenceException, поскольку базовый DbSet всегда имеет значение null. Код делает следующее:

В BaseClass;

public IEnumerable<T> GetAll() 
{ 
    return _dbSet.AsEnumerable(); 
} 

В подклассе;

public User GetById(int id) 
     { 
      return GetAll().FirstOrDefault(x => x.Id == id); 
     } 

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

Для справки, это статья MSDN, что тот же самый код с модификацией скомпилируйте его.

https://msdn.microsoft.com/en-us/data/dn314429.aspx

РЕДАКТИРОВАТЬ:

Уменьшение сложности UserService (его использование дженериков/интерфейсов), код теперь просто;

public User GetById(int id) 
     { 
      return _dbContext.Set<User>().FirstOrDefault(x => x.Id == id); 
     } 

Если я изменю это дальше;

var dbSet = _dbContext.Set<User>(); 
     return dbSet.FirstOrDefault(x => x.Id == id); 

Я отчетливо вижу, что dbSet имеет значение null.

Edit 2

Согласно предложению от wablab, оказывается, что издеваться .С проблема решена.

Кредит также Владиславу Кушниру за общий метод для DbSet.

Рабочий код для этого для тех, кому это может понадобиться;

private static Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class 
     { 
      if (items == null) 
      { 
       items = new T[0]; 
      } 

      var dbSetMock = new Mock<DbSet<T>>(); 
      var q = dbSetMock.As<IQueryable<T>>(); 

      q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); 

      return dbSetMock; 
     } 



var mockContext = new Mock<Model1>(); 

var users = new List<User> { new User { Email = "[email protected]", Id = 1 } }; 

mockContext.Setup(x => x.Set<User>()).Returns(GetDbSetMock(users).Object); 

var service = new UsersService(mockContext.Object); 

var user = service.GetById(1); 
+0

Вы подтвердили, что ваш конструктор 'UserService' назначает свойство' Users' параметра, которое оно передано в поле '_dbSet'? – wablab

+0

Он работает незатронутым, если это то, что вы имеете в виду. – ChrisBint

+0

Является ли 'NullReferenceException' выбрасывается из метода GetById или метода GetAll? Другими словами, это '_dbSet' null или результат' _dbSet.AsEnumerable() 'null? (Или что-то еще пустое?) – wablab

ответ

3

Я думаю, вам нужно создать установку по методу Set<User>(), чтобы вернуть издеваться.

+0

Работал отлично. благодаря – ChrisBint

0
private Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class 
    { 
     if (items == null) 
     { 
      items = new T[0]; 
     } 

     var dbSetMock = new Mock<DbSet<T>>(); 
     var q = dbSetMock.As<IQueryable<T>>(); 

     q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator); 

     return dbSetMock; 
    } 

Вот мой довольно хорошо работает универсальный метод я использую для насмешливого DbSet из DbContext. Actuall вызов этого метода:

var contextMock = new Mock<MyContext>(); 
contextMock.Setup(x => x.MyDbEntities).Returns(GetDbSetMock<MyDbEntity>().Object); 
+0

Как ни странно, это не работает на моей машине, dbset все еще имеет нулевое значение, используя этот код. – ChrisBint

+0

Также в моем контексте я использую 'IDbSet' вместо' DbSet', попробуйте это, возможно, это поможет. –

+0

Возможно, этот код не работает, потому что вы издеваетесь над конкретным свойством DbContext, в то время как вы пытаетесь получить доступ к данным через 'Set ', попробуйте дополнительно издеваться над этим методом. –

Смежные вопросы