使代码内部但可用于其他项目的单元测试

时间:2008-09-20 03:10:29

标签: c# unit-testing scope

我们将所有单元测试都放在他们自己的项目中。我们发现我们必须将某些类公开而不是内部仅用于单元测试。无论如何都要避免这样做。将课程公开而不是密封是什么意思?

5 个答案:

答案 0 :(得分:185)

如果您使用的是.NET,则InternalsVisibleTo程序集属性允许您创建“朋友”程序集。这些是特定的强名称程序集,允许访问内部类和其他程序集的成员。

请注意,这应该谨慎使用,因为它紧密地耦合了所涉及的组件。 InternalsVisibleTo的常见用途是用于单元测试项目。由于上述原因,它可能不适合在您的实际应用程序集中使用。

示例:

[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{

答案 1 :(得分:6)

如果是内部类,则不能单独使用它。因此,除了测试一些在内部使用该对象的其他类之外,你不应该真正测试它。

正如您不应该测试类的私有成员一样,您不应该测试DLL的内部类。这些类是一些可公开访问的类的实现细节,因此应该通过其他单元测试来很好地运用。

这个想法是你只想测试一个类的行为,因为如果你测试内部实现细节,那么你的测试就会很脆弱。您应该能够在不破坏所有测试的情况下更改任何类的实现细节。

如果您发现确实需要测试该类,那么您可能需要首先重新检查该类为什么是内部的。

答案 2 :(得分:3)

用于文档目的

或者,您可以使用Type.GetType方法

来实例化内部类

例如

//IServiceWrapper is public class which is 
//the same assembly with the internal class 
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
    .CreateInstance(type, new object[1] { /*constructor parameter*/ });

对于泛型类型,有不同的过程如下:

var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
     .CreateInstance(genType, new object[1] { /*constructor parameter*/});

答案 3 :(得分:1)

以下是在 .NET Core 应用程序中使用的方法。

  1. 添加 AssemblyInfo.cs 文件并添加 [assembly: InternalsVisibleTo("AssemblytoVisible")]
  2. 将其添加到 .csproj 文件 (包含内部类的项目)
<ItemGroup>
  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
    <_Parameter1>Test_Project_Name</_Parameter1> <!-- The name of the project that you want the Internal class to be visible To it -->
  </AssemblyAttribute>
</ItemGroup>

更多信息请关注https://improveandrepeat.com/2019/12/how-to-test-your-internal-classes-in-c/

答案 4 :(得分:-4)

课程既可以公开也可以密封。

但是,不要这样做。

您可以创建一个工具来反映内部类,并发出一个通过反射访问所有内容的新类。 MSTest做到了。

编辑:我的意思是,如果您不想在原始程序集中包含-any-测试内容;如果成员是私人的,这也有效。