解决问题
  那如何mock呢?比想象中复杂得多,幸好在msdn网站上发现了现成的mock实现代码(详见 Testing with a mocking framework ),照此可以轻松mock。
  mock之前需要实现这三个接口:IDbAsyncEnumerator,IDbAsyncEnumerable,IDbAsyncQueryProvider 。
1)TestDbAsyncEnumerator 实现 IDbAsyncEnumerator
public class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public T Current
{
get { return _inner.Current; }
}
object IDbAsyncEnumerator.Current
{
get { return Current; }
}
}
2)TestDbAsyncEnumerable 实现 IDbAsyncEnumerable
public class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }
public TestDbAsyncEnumerable(Expression expression)
: base(expression)
{ }
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
get { return new TestDbAsyncQueryProvider<T>(this); }
}
}
3)TestDbAsyncQueryProvider 实现 IDbAsyncQueryProvider
public class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
private readonly IQueryProvider _inner;
public TestDbAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestDbAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestDbAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
  然后将之前的mock代码:
  var mockUnitOfWork = new Mock<IUnitOfWork>();
  mockUnitOfWork.Setup(u => u.Set<BlogCategory>()).Returns(blogCategories);
  改为下面的代码:
  #region mockSet
  var mockSet = new Mock<DbSet<BlogCategory>>();
  mockSet.As<IDbAsyncEnumerable<BlogCategory>>()
  .Setup(m => m.GetAsyncEnumerator())
  .Returns(new TestDbAsyncEnumerator<BlogCategory>(blogCategories.GetEnumerator()));
  mockSet.As<IQueryable<BlogCategory>>()
  .Setup(m => m.Provider)
  .Returns(new TestDbAsyncQueryProvider<BlogCategory>(blogCategories.Provider));
  mockSet.As<IQueryable<BlogCategory>>().Setup(m => m.Expression).Returns(blogCategories.Expression);
  mockSet.As<IQueryable<BlogCategory>>().Setup(m => m.ElementType).Returns(blogCategories.ElementType);
  mockSet.As<IQueryable<BlogCategory>>().Setup(m => m.GetEnumerator()).Returns(blogCategories.GetEnumerator());
  #endregion
  var mockUnitOfWork = new Mock<IUnitOfWork>();
  mockUnitOfWork.Setup(u => u.Set<BlogCategory>()).Returns(mockSet.Object);
  这样成功mock出DbSet之后,单元测试成功通过,问题解决了。
  1 passed, 0 failed, 0 skipped, took 2.75 seconds (xUnit.net 1.9.2 build 1705).