C# 如何访问另一个程序集中的类以进行单元测试?

C# 如何访问另一个程序集中的类以进行单元测试?,c#,unit-testing,.net-assembly,C#,Unit Testing,.net Assembly,我正以VisualStudio2008的方式进行单元测试,我想知道为了测试目的实现跨汇编类访问的最佳方法是什么 基本上,我在一个解决方案中有两个项目: 我的项目(C#) MyProjectTests(C#测试项目) MyProject中的所有内容当前都具有默认的可访问性,如果我回忆正确,这意味着所有内容实际上都是内部的。我主要希望在类级别上进行测试,但也有一些学员参与其中 将来可能会有一个外部API,但我已经完成了大约20%的功能(至少在纸面上),而且我对在这个未经测试的核心之上分层更多的代码非

我正以VisualStudio2008的方式进行单元测试,我想知道为了测试目的实现跨汇编
访问的最佳方法是什么

基本上,我在一个解决方案中有两个项目:

  • 我的项目(C#)
  • MyProjectTests(C#测试项目)
  • MyProject中的所有内容当前都具有默认的可访问性,如果我回忆正确,这意味着所有内容实际上都是内部的。我主要希望在
    级别上进行测试,但也有一些
    学员参与其中

    将来可能会有一个外部API,但我已经完成了大约20%的功能(至少在纸面上),而且我对在这个未经测试的核心之上分层更多的代码非常谨慎。因此,我想现在就做一些测试,在应用程序完成传统(读:糟糕和/或懒惰)功能测试之前,以及在版本n+1外部API发布之前


    除了直截了当的回答外,请举一个解决方案的例子。

    您可以使用assembly level属性来实现这一点

    到MyProject程序集中的AssemblyInfo.cs。您需要添加

    [assembly:InternalsVisibleTo("Unit.Tests.Assembly")] 
    
    到您的“MyProject(C#)”的AssemblyInfo.cs。这样,您的测试就可以访问用于测试的内部方法。

    看起来您需要


    但是,我建议不要使用这种方法-通过公共接口或API测试内部类。

    您可以测试内部方法,方法是为主项目的AssemblyInfo.cs添加一个属性,允许访问命名程序集的内部方法:

    [汇编:InternalsVisibleTo(“MyProjectTestsNameSpace.MyProjectTests”)]


    进一步的信息是

    虽然
    [InternalsVisibleTo]
    是IMO最明智的方法,但至少还有两种方法可以做到这一点:

    • 利用

    这种方法的问题是,如果方法名称或签名发生更改,单元测试将在运行时开始失败,而
    [InternalsVisibleTo]
    则很容易在编译时发现这种破坏性的更改

    • 使用测试框架,如或
    我发现了这个,希望它能帮助别人

    总结:

    • 在单元测试项目中,添加对测试代码的引用。以下是如何在同一解决方案中创建对代码项目的引用:
    • 在解决方案资源管理器中选择项目
    • 在“项目”菜单上,选择“添加引用…”
    • 在“引用管理器”对话框中,打开“解决方案”节点并选择“项目”
    • 检查代码项目名称并关闭对话框

    问题是这些还不存在;暂时不会。这是一个很大的项目(或者说,当它完成的时候就会发生)。由内而外的方法的问题是,你可能会遇到这样一种情况,即你已经完成了内部工作。。但是外部API并没有像预期的那样插入,因为在理解上存在脱节。反馈要晚得多。。是的,但是在应用程序“完成”之前推迟彻底的测试只是在自找麻烦。此外,外部API可能会采取自动化用户操作和提取数据的形式,而不是扩展功能;与成熟的插件API相比,要搞砸要困难得多。我不主张直到最后才进行测试。。我想说的是,从外到内形成垂直薄片。但是,您更了解您的具体情况—如果风险最小,则无所谓。为了避免您的下一个问题—如果已对测试程序集进行签名,为什么必须对测试程序集进行签名?--下面是我关于这个主题的文章:当然,在包含适当的强名称键引用的情况下——您正在对程序集进行强命名,不是吗。链接已断开:(
    [assembly:InternalsVisibleTo("Unit.Tests.Assembly")] 
    
     var method = instance.GetType().GetMethod(
        methodName, BindingFlags.NonPublic | BindingFlags.Instance, 
        null, paramTypeArray, null);
     return method.Invoke(instance, parameters);