如何在NUnit中测试私有变量?

9

我有一个静态类,其中有一个私有变量。

private static Dictionary<strng, string> items = new Dictionary<string, string>();

该类的许多公共方法都会访问此字典对象。现在我想编写一个NUnit测试类(在不同的库中)。如何测试这个私有变量?

4个回答

9
我不会讨论是否应该测试内部类的内部方法。您可以使用InternalsVisibleToAttribute属性将内部方法/属性/类等暴露给外部库。
例如,如果您的单元测试库名为MyUnitTestsLibrary,只需在项目(被测试的那个)的AssemblyInfo.cs文件中添加以下内容。
[assembly:InternalsVisibleTo("MyUnitTestsLibrary")]

这将使得 MyUnitTestsLibrary 库成为被测试项目的友元库,并暴露出其所有内部内容,以便进行单元测试。

1
如果使用已签名的程序集,这将导致一系列问题。 - eri0o
@eri0o 能否详细说明一下?我很想知道为什么这可能会在未来引起问题。 - Cullub

6
我知道这个问题与 NUnit 有关,我不想争论测试私有成员是好还是坏的实践。事实上,有时候这是必要的,特别是当你不得不处理遗留或设计不良的代码而无法重构时。
因此,我想提到 Gallio/MbUnit 提供了一个轻量级的 API,称为 Mirror,以便于测试私有类型成员。
示例:下面的测试样本调用了foo实例上名为SomePrivateMethod的私有方法。
[Test]
public void SampleTest()
{
   var foo = new Foo();
   int actual = Mirror.ForObject(foo)["SomePrivateMethod"].Invoke();
   Assert.AreEqual(123, actual);
}

2
MSTest通过其Accessor功能提供了相同的功能。但是,单元测试仍然没有意义,因为您应该针对单元进行测试,而不是其内部实现。 - Lex Li

3

你不需要测试私有变量,而是要测试类的行为。

这意味着你应该只测试类的公共接口。

请参考这个问题。


谢谢你的回答。然而,我发现很多人支持“只测试公共接口还是私有方法也应该测试”的辩论双方。所以,如果我需要测试私有变量,是否有什么解决办法? - Learner
可以,因为使用反射,例如,您可以绕过C#的封装。也许Yann的答案可以帮助您。无论如何,如果我是您,我会寻找另一种方法。 - Simone
被踩了:Yann的回答更好,这个回答没有帮助性,而且狭隘,假设作者的观点是唯一正确的观点。 - Quango

2

在进行单元测试时,应该测试公共接口,而不是私有实现。检查接口在执行操作时是否按预期运行,而不检查字典本身。这样,如果您将来决定使用不同的数据结构替换字典,就不会破坏所有测试。


谢谢您的回答。然而,我发现很多人支持“只测试公共接口还是私有方法也应该测试”的辩论双方。所以,如果我需要测试私有变量,是否有什么解决办法? - Learner
如果你确实需要这样做,可以尝试 Yann 的方法。但它背后的思想是,你的类与系统其他部分交互的唯一方式是通过其公共接口,因此您只需要测试公共接口。您的类如何选择 实现该接口取决于您,只要您通过公共接口履行义务即可。彻底测试它,并且在实现上进行测试是不必要和脆弱的(会因更改而容易破裂)。 - Jackson Pope

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接