So EntityFramework 6 is a lot better testable then previous versions. And there are some nice examples on the internet for frameworks like Moq, but the case is, I prefer usi
Thanks to Kevin, I've found the problem in my code translation.
The unittest code samples are mocking DbSet, but NSubstitute requires the interface implementation. So the equivalent of Moqs new Mock for NSubstitute is Substitute.For. You're not always required to provide the Interface, so that's why I was confused. But in this specific case, it turned out to be crucial.
It also turned out that we don't have to cast to Queryable when using the interface IDbSet.
So the working test code:
public void GetAllBlogs_orders_by_name()
{
// Arrange
var data = new List
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();
var mockSet = Substitute.For>();
mockSet.Provider.Returns(data.Provider);
mockSet.Expression.Returns(data.Expression);
mockSet.ElementType.Returns(data.ElementType);
mockSet.GetEnumerator().Returns(data.GetEnumerator());
var mockContext = Substitute.For();
mockContext.Blogs.Returns(mockSet);
// Act and Assert ...
}
I've written a small extention method to cleanup the Arrange section of the unit tests.
public static class ExtentionMethods
{
public static IDbSet Initialize(this IDbSet dbSet, IQueryable data) where T : class
{
dbSet.Provider.Returns(data.Provider);
dbSet.Expression.Returns(data.Expression);
dbSet.ElementType.Returns(data.ElementType);
dbSet.GetEnumerator().Returns(data.GetEnumerator());
return dbSet;
}
}
// usage like:
var mockSet = Substitute.For>().Initialize(data);
Not the question, but in case you also need to be able to support async operations:
public static IDbSet Initialize(this IDbSet dbSet, IQueryable data) where T : class
{
dbSet.Provider.Returns(data.Provider);
dbSet.Expression.Returns(data.Expression);
dbSet.ElementType.Returns(data.ElementType);
dbSet.GetEnumerator().Returns(data.GetEnumerator());
if (dbSet is IDbAsyncEnumerable)
{
((IDbAsyncEnumerable) dbSet).GetAsyncEnumerator()
.Returns(new TestDbAsyncEnumerator(data.GetEnumerator()));
dbSet.Provider.Returns(new TestDbAsyncQueryProvider(data.Provider));
}
return dbSet;
}
// create substitution with async
var mockSet = Substitute.For, IDbAsyncEnumerable>().Initialize(data);
// create substitution without async
var mockSet = Substitute.For>().Initialize(data);