【问题标题】:Moq DbSet NotImplementedExceptionMoq DbSet NotImplementedException
【发布时间】:2017-09-15 17:08:21
【问题描述】:

我有一个最近一直在工作的 Moq DbSet,但是自从上次更新依赖项以来,它一直在 IQueryable.Provider 上抛出 NotImplementedException

使用的代码如下:

var mockSet = new Mock<DbSet<A>>();
var list = new List<A>();
var queryable = list.AsQueryable();
mockSet.As<IQueryable<A>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockSet.As<IQueryable<A>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockSet.As<IQueryable<A>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockSet.As<IQueryable<A>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

var f =mockSet.Object.FirstOrDefault(); // NotImplementedException thrown here

抛出的异常如下:

System.NotImplementedException
The member 'IQueryable.Provider' has not been implemented on type
'DbSet`1Proxy_1' which inherits from 'DbSet`1'.
Test doubles for 'DbSet`1' must provide implementations of methods
and properties that are used.

【问题讨论】:

  • 这篇 Microsoft 文章提供了一种实现,允许您使用内存中的测试替身。我刚刚更新了我的 Moq 4.7.99 和 Castle.Core 4.1.1,我的测试通过了。 msdn.microsoft.com/en-us/library/dn314431(v=vs.113).aspx
  • 这很有帮助。可悲的是,我经常发现更高级的 MSDN 文章基本上只是被编成一个庞大的列表。
  • 在内存数据库中使用Sqlite 将提供更好的测试体验,因为您不受如何构建查询的限制。只需插入所需数据,运行查询,检查预期结果

标签: c# entity-framework moq dbset


【解决方案1】:

您可能一直在使用 4.7.58 版本的 Moq。该特定版本受到a regression 的影响,它会触发这样的NotImplementedException。该回归 has been fixed 在版本 4.7.63 中,因此我建议您将 Moq 包参考更新到版本 4.7.63 或更高版本以解决此问题。

您的代码可以在 4.7.58 之前的最小起订量版本中运行的事实是由于一个“功能”,不幸的是,它导致的问题比解决的问题多得多。因此,该功能was reverted

Moq 已恢复到原来的行为,在这种特殊情况下,您需要通过mock.As&lt;TInterface&gt; 设置各种接口成员调用mock.Object 。 (通常,在 Moq 中,即使在检索到 mock 对象之后执行更多设置也完全没问题;这种情况是一个值得注意的例外。希望这可以在 Moq 的未来版本中得到修复。)

【讨论】:

  • 这是否意味着我必须在这种情况下基本上使用 mock.As().Object ?根据我的 Git 历史,问题发生在 Moq 4.7.99 和 Castle.Core 4.1.1.0 上,代码与上面提供的完全相同。
  • 从 4.7.25 更新到 4.7.99 后,问题又出现了。
  • @DanielRusznyak:鉴于您在上面发布的代码,并使用 Moq 4.7.99,我无法重现您所说的错误。它编译并运行没有任何错误。您确定您的复制代码中没有遗漏任何内容吗?您的目标是哪个版本的实体框架?
  • 其实查了一下,这个问题是在设置Provider之前的一个流浪的mock.Object.Add()调用,在完全不同的地方抛出了一个错误旧版本忽略了这个问题,但是新版本版本在下一个 mock.Object.FirstOrDefault() 上失败,NotImplementedException 没有指出真正的问题。
  • 回复:“问题是在设置之前的一个流浪 mock.Object.Add() 调用” - 是的,根据第 3 段,就是这样。回复:“旧版本忽略了这个问题” - 它没有忽略它;事实上,我在回答的第 2 段中提到的有问题的特性正是使早期的 mock.Object 调用能够在 EF 测试中工作的原因(以破坏大量其他同样可能的用例为代价)。
【解决方案2】:

将 Castle.Core 回滚到 4.0.0 并将 Moq 回滚到支持 4.0.0 的最新版本解决了这个问题。我仍然想知道是否有一些我遗漏的东西可以在新版本中解决这个问题。

【讨论】:

  • 在新版本中修复(新含义,此时为 4.7.99)。事实上,您的代码也适用于 4.7.63 版本;见my answer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2017-03-21
  • 2015-09-29
  • 2020-07-06
  • 1970-01-01
  • 2011-04-15
  • 1970-01-01
相关资源
最近更新 更多