MoQ: свойство правильно установлено как виртуальное, но все еще имеет недопустимую настройку для не виртуального члена
Я хотел бы провести модульное тестирование DbContext, который наследуется от IdentityDbContext
Я получаю NotSupportedException
сообщение об ошибке с очень распространенным сообщением:
System.NotSupportedException: неверная установка для не виртуального (переопределяемого в VB) члена
Чтобы найти подсказки, я уже прочитал кучу постов. Вот несколько примеров:
Очевидно, что решение, по-видимому, устанавливает dbSet как виртуальный. Что я сделал.
Не повезло, ошибка остается.
Вот мой IdentityDataContext:
public class IdentityDataContext : IdentityDbContext<ApplicationUser>
{
public virtual DbSet<Search> Searches { get; set; }
public IdentityDataContext()
: base("LocalDb",
throwIfV1Schema: true)
{
}
public static IdentityDataContext Create()
{
return new IdentityDataContext();
}
}
Вот мой поиск POCO:
public class Search : BaseEntity
{
//BaseEntity is just an abstract class with createdAt,Id,updatedAt property
public string ConsumerIdentifier { get; set; }
public string LanguageCode { get; set; }
}
Наконец, вот мой метод настройки:
[TestInitialize]
public void SetupTest()
{
//DataInitializer.GetAllSearches() returns a List of "Search"
_searches = DataInitializer.GetAllSearches();
var dbSet = new Mock<DbSet<Search>>();
dbSet.As<IQueryable<Search>>().Setup(m => m.Provider).Returns(_searches.AsQueryable().Provider);
dbSet.As<IQueryable<Search>>().Setup(m => m.Expression).Returns(_searches.AsQueryable().Expression);
dbSet.As<IQueryable<Search>>().Setup(m => m.ElementType).Returns(_searches.AsQueryable().ElementType);
dbSet.As<IQueryable<Search>>().Setup(m => m.GetEnumerator()).Returns(_searches.AsQueryable().GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<Search>())).Callback<Search>(_searches.Add);
_dataContextMock = new Mock<IdentityDataContext>()
{
CallBase = true
};
// The error appears here ---------------- _
dataContextMock.Setup(x => x.Searches).Returns(dbSet.Object);
//----------------------------------------------------------------------
_dataContextMock.Setup(x => x.Set<Search>()).Returns(dbSet.Object);
_searchRepository = new SearchRepository(_dataContextMock.Object);
}
Что мне не хватает?
1 ответ
1) нет необходимости в модульном тестировании DbContext. Microsoft уже провела бы обширные испытания на нем.
2) если DbContext должен использоваться как зависимость для другого класса, тогда абстрагируйте dbcontext
public interface IDataContext {
DbSet<Search> Searches { get; set; }
}
public class IdentityDataContext : IdentityDbContext<ApplicationUser>, IDataContext { ... }
public class SearchRepository {
public SearchRepository(IDataContext context) { ... }
}
У вас нет занятий в зависимости от конкреций, а скорее от абстракций. IdentityDataContext
это деталь реализации, о которой зависимые классы не должны знать
Это тогда позволило бы больше гибкости для тестирования
Mock<IDataContext> _dataContextMock;
[TestInitialize]
public void SetupTest() {
//DataInitializer.GetAllSearches() returns a List of "Search"
_searches = DataInitializer.GetAllSearches();
var queryable = _searches.AsQueryable();
var dbSet = new Mock<DbSet<Search>>();
dbSet.As<IQueryable<Search>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<Search>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<Search>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<Search>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<Search>())).Callback<Search>(_searches.Add);
_dataContextMock = new Mock<IDataContext>();
_dataContextMock.Setup(x => x.Searches).Returns(dbSet.Object);
_dataContextMock.Setup(x => x.Set<Search>()).Returns(dbSet.Object);
_searchRepository = new SearchRepository(_dataContextMock.Object);
}