Reputation: 43
I'd like to unit test a DbContext which inherits from IdentityDbContext
I am getting a NotSupportedException
error message with the very common message :
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member
To find some clues I already read a bunch of posts. Here are some samples:
Obviously, the solution appears to set the dbSet as virtual. What I've done.
Bad luck, the error remains.
Here is my 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();
}
}
Here is my Search 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; }
}
Finally here is my Set Up Method :
[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);
}
What am I missing?
Upvotes: 4
Views: 980
Reputation: 247551
1) no need to unit test DbContext. Microsoft would have done extensive testing on it already.
2) if the DbContext is to be used as a dependency for another class then abstract the dbcontext
public interface IDataContext {
DbSet<Search> Searches { get; set; }
}
public class IdentityDataContext : IdentityDbContext<ApplicationUser>, IDataContext { ... }
public class SearchRepository {
public SearchRepository(IDataContext context) { ... }
}
Don't have you classes depending on concretions but rather on abstractions. IdentityDataContext
is an implementation detail that dependent classes need not know about.
This would then allow more flexibility for testing
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);
}
Upvotes: 0