Я нашел несколько примеров, которые показывают (по-видимому) ясный рабочий пример издевательского 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);
Вы подтвердили, что ваш конструктор 'UserService' назначает свойство' Users' параметра, которое оно передано в поле '_dbSet'? – wablab
Он работает незатронутым, если это то, что вы имеете в виду. – ChrisBint
Является ли 'NullReferenceException' выбрасывается из метода GetById или метода GetAll? Другими словами, это '_dbSet' null или результат' _dbSet.AsEnumerable() 'null? (Или что-то еще пустое?) – wablab