【问题标题】:Build failure in unit test project with accessors of a project containing covariant types使用包含协变类型的项目的访问器在单元测试项目中构建失败
【发布时间】:2010-09-08 09:16:15
【问题描述】:

我为我们的项目添加了一个协变接口:

interface IView
{
}

interface IPresenter<out TView> where TView : IView
{
    TView View { get; }
}

我创建了一些类,实现了这些接口:

class TestView : IView
{
}

class TestPresenter : IPresenter<TestView>
{
  public TestView View
  {
    get { return something; }
  }

  private void DoSomething()
  {
  }
}

我可以毫无问题地使用它:

IPresenter<IView> presenter = new TestPresenter();

所以一切似乎都是正确的,所以我假设我的协方差使用是正确的。不幸的是,我们的单元测试项目包含来自同一项目中某些类型的私有访问器,例如协变接口,这会导致构建失败。

无法加载类型 'GenericInheritanceTest.IPresenter_Impl`1' 从组装 'GenericInheritanceTest_Accessor, 版本=0.0.0.0,文化=中性, PublicKeyToken=null' 因为它 声明协变或逆变 类型参数并且不是接口 或委托。

这里到底有什么问题?我的实施是否有失败,分别。如何解决这个问题?不可能,一旦我们使用协变类型,我们就必须避免访问器???是否可以阻止为某些类型创建访问器来解决这个问题?

【问题讨论】:

  • 一般情况下,您应该避免使用私有访问器 - 它们会导致测试和生产代码之间的耦合过紧。
  • 是的,谢谢,但是我这里有一个已经存在的项目,它有 120k loc 并且很好地使用了私有访问器,所以重做它不仅仅是指尖。

标签: c# unit-testing covariance accessor


【解决方案1】:

这是 Visual Studio 2010 中的一个错误。已向 Microsoft Connect 报告,但已关闭,显然不会修复。

根据 Bruce Taimana 的博客文章,the private accessor feature 的开发已停止,并且可能会在 Visual Studio 的未来版本中被删除。列出的可能替代方案是:

  1. 使用Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject 类来帮助访问代码中的内部和私有 API。这可以在 Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll 程序集中找到。

  2. 创建一个能够反射您的代码以访问内部或私有 API 的反射框架。

  3. 如果您尝试访问的代码是内部代码,您可以使用InternalsVisibleToAttribute 访问您的 API,以便您的测试代码可以访问内部 API。

【讨论】:

  • 一个迟到的答案,但谢谢 :) 是的,私有访问器已被弃用,同时我们删除了项目中的所有私有访问器。从您的解决方案列表中,我更喜欢第 4 点。使用良好的对象结构 (IoC) 提高可测试性:)
【解决方案2】:

我一直在努力解决这个错误,但也遇到了错误:“BuildShadowTask”意外失败。当我尝试在此处解决该错误时,摆脱该错误的唯一方法是从泛型中删除 out 关键字,即协变接口。

实际上,当 Resharper 向我建议类型参数可能是协变时,我得到了这个错误:

private delegate TResult Action<TResult>(); 

改为:

private delegate TResult Action<out TResult>();

遗憾的是,我不得不再次将其改回并在评论中禁用 Resharper 警告:

// ReSharper disable once TypeParameterCanBeVariant 
private delegate TResult Action<TResult>();

因此,一种策略可以是搜索:

"<out"

在一个项目中并删除 out 关键字,只是为了让它编译。 不是很优雅,但微软也不是很优雅,因为 这是五年前通过 Microsoft Connect 报告的,他们 选择了只是关闭问题。问题出在单元测试项目中。这无济于事 从 Visual Studio 单元测试框架更改为 NUnit 测试框架。

【讨论】:

    【解决方案3】:

    如果您使用 Unity Interception,并且您的参数标记为 out,则 Unity Interception 会导致此错误。这样做的原因是 Interception 必须能够读取参数列表。所以和上面的情况类似,如果 Resharper 警告参数可以是协变的,这个警告需要忽略。

    【讨论】:

      猜你喜欢
      • 2011-09-08
      • 2018-06-22
      • 2021-01-28
      • 2018-10-03
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-17
      相关资源
      最近更新 更多