将代码设为内部代码,但可用于其他项目的单元测试

问题描述 投票:0回答:6

我们将所有单元测试放在他们自己的项目中。我们发现我们必须将某些类公开而不是仅用于单元测试的内部类。无论如何,有没有办法避免这样做。将类公开而不是密封对内存有什么影响?

c# unit-testing scope
6个回答
237
投票

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

请注意,应谨慎使用,因为它紧密耦合相关的程序集。 InternalsVisibleTo 的常见用途是单元测试项目。由于上述原因,在实际的应用程序程序集中使用它可能不是一个好的选择。

示例:

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

16
投票

以下是在 .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
投票

如果它是一个内部类,那么它一定不能被单独使用。因此,除了测试内部使用该对象的其他类之外,您不应该真正测试它。

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

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

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


4
投票

用于文档目的

或者,您可以使用

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*/});

0
投票

现在已经是 2023 年了,现在可以通过使用 UnsafeAccessorAttribute 的 dotnet 8 实现这一点。在 dotnet 8 之前,解决方案是使用内部关键字(这不能回答问题,因为内部与私有不同)或使用反射,速度非常慢。 现在在 dotnet 8 中,您可以访问私有字段而无需使用反射:

https://www.meziantou.net/accessing-private-members-without-reflection-in-csharp.htm


-6
投票

课程可以是公开的,也可以是密封的。

但是,不要这样做。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.