如何用NUnittesting私有方法?

我想知道如何正确使用NUnit。 首先,我创build了一个单独的testing项目,使用我的主项目作为参考。 但在这种情况下,我无法testing私人方法。 我的猜测是,我需要包括我的testing代码到我的主代码?! – 这似乎不是正确的做法。 (我不喜欢用代码运输代码的想法。)

如何用NUnittesting私有方法?

一般来说,unit testing是针对一个类的公共接口,只要结果从客户的angular度来看是正确的,理论上这个实现是不重要的。

所以,NUnit没有提供任何testing非公开成员的机制。

编写unit testing的通用模式是只testing公共方法。

如果你发现你有很多你想testing的私有方法,通常这是一个标志,你应该重构你的代码。

把这些方法公布在他们目前生活的class上是错误的。 那会打破你想让这个class级拥有的合同。

将他们转移到帮助者class级并在那里公开是正确的。 这个类可能不会被你的API暴露。

这种方式testing代码从来没有与您的公共代码混合。

类似的问题是testing私人类,即。 你不从你的程序集导出的类。 在这种情况下,您可以使用属性InternalsVisibleTo将您的testing代码程序集明确地作为生产代码程序集的朋友。

虽然我同意unit testing的重点应该是公共接口,但是如果您也testing私有方法,您会对代码有更为细微的印象。 MStesting框架允许通过使用PrivateObject和PrivateType,NUnit不支持。 我所做的是:

 private MethodInfo GetMethod(string methodName) { if (string.IsNullOrWhiteSpace(methodName)) Assert.Fail("methodName cannot be null or whitespace"); var method = this.objectUnderTest.GetType() .GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance); if (method == null) Assert.Fail(string.Format("{0} method not found", methodName)); return method; } 

这意味着您不必为了可testing性而妥协封装。 请记住,如果要testing私有静态方法,则需要修改BindingFlags。 上面的例子只是一些方法。

可以通过将testing程序集声明为正在testing的目标程序集的朋友程序集来testing私有方法。 详情请看下面的链接:

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

这可能是有用的,因为它主要是从生产代码中分离出你的testing代码。 我从来没有使用过这种方法,因为我从来没有发现它的需要。 我想你可以用它来试验和testing你的testing环境中无法复制的极端testing用例,以查看你的代码如何处理它。

正如前面所说,你真的不需要testing私有方法。 你不仅仅想把你的代码重构成更小的构build块。 一个可以帮助你重构的技巧是尝试考虑你的系统所涉及的领域,并考虑这个领域的“真实”对象。 您的系统中的对象/类应该直接与真实对象相关联,这将允许您隔离对象应该包含的确切行为,并限制对象的责任。 这意味着你在逻辑上重构,而不仅仅是为了testing一个特定的方法。 你将能够testing对象的行为。

如果你仍然觉得需要testing内部,那么你可能也想考虑在你的testing中嘲笑,因为你可能想专注于一段代码。 嘲笑是注入对象依赖关系的地方,但注入的对象不是“真实”对象或生产对象。 它们是具有硬编码行为的虚拟对象,可以更容易地隔离行为错误。 Rhino.Mocks是一个非常受欢迎的免费嘲笑框架,它将基本上为您编写对象。 TypeMock.NET(一个带有社区版的商业产品)是一个function更强大的框架,可以模拟CLR对象。 例如在testing数据库应用程序时,模拟SqlConnection / SqlCommand和Datatable类非常有用。

希望这个答案会给你更多的信息,告诉你一般的unit testing,并帮助你从unit testing中获得更好的结果。

unit testing的主要目标是testing一个类的公共方法。 这些公共方法将使用这些私有方法。 unit testing将testing公开可用的行为。

我赞成有能力testing私人方法。 当xUnit开始的时候,它是用来在代码写入之后testingfunction的。 testing界面就足够了。

unit testing已经发展到testing驱动的开发。 具有testing所有方法的function对于该应用程序非常有用。

这个问题已经过了很多年了,但是我想我会分享一下我的做法。

基本上,我在我们所有的unit testing类中,他们正在testing的'unit testing'命名空间下方的默认'该组件 – 每个testing文件被包装在一个:

 #if DEBUG ...test code... #endif 

块,所有这一切都意味着a)它不会被分发到一个版本中,并且b)我可以使用internal / Friend级别的声明,而不会箍跳。

另一件事情,这个问题更为贴切的是使用了partial类,它可以用来创build一个testing私有方法的代理,例如testing类似于返回一个整数值的私有方法:

 public partial class TheClassBeingTested { private int TheMethodToBeTested() { return -1; } } 

在汇编的主要类中,以及testing类:

 #if DEBUG using NUnit.Framework; public partial class TheClassBeingTested { internal int NUnit_TheMethodToBeTested() { return TheMethodToBeTested(); } } [TestFixture] public class ClassTests { [Test] public void TestMethod() { var tc = new TheClassBeingTested(); Assert.That(tc.NUnit_TheMethodToBeTested(), Is.EqualTo(-1)); } } #endif 

很明显,你需要确保在开发过程中不使用这个方法,但是如果你这样做的话,Release版本很快就会显示一个无意的调用。

道歉,如果这不回答这个问题,但解决scheme,如使用reflection,#if #endif语句或使私有方法可见不能解决问题。 可以有几个原因使得私有方法不可见…如果是生产代码和团队是回顾性编写unit testing的话会怎么样?

对于我正在处理的项目,只有MSTest(可惜)似乎有一种方法,使用访问器来unit testing私有方法。

你不testing私人function。 有办法使用reflection来进入私人的方法和属性。 但这并不容易,我强烈反对这种做法。

你根本不应该testing任何不公开的东西。

如果你有一些内部的方法和属性,你应该考虑把它改为公开的,或者用应用程序发布你的testing(我真的不认为是一个问题)。

如果你的客户能够运行一个testing套件,并看到你提供的代码实际上是“工作的”,我不认为这是一个问题(只要你不通过这个放弃你的IP)。 我在每个版本中包含的东西都是testing报告和代码覆盖率报告。

我会使私有方法包可见。 这样,你可以保持合理的私密性,同时还能够testing这些方法。 我不同意那些说公共接口是唯一需要testing的人。 私有方法中经常存在非常关键的代码,只能通过外部接口进行正确的testing。

所以这真的归结为如果你更关心正确的代码或信息隐藏。 我想说包可见性是一个很好的妥协,因为为了访问这些方法,有人不得不把他们的类放在你的包中。 这真的应该让他们三思而后行,这是否是一个非常聪明的事情。

我是一个Java的人,所以在C#中,可视化包可能被称为完全不同的东西。 只要说两个类必须位于相同的命名空间才能访问这些方法即可。

您可以使您的方法受到内部保护,然后使用assembly: InternalVisibleTo("NAMESPACE")到您的testing命名空间。

因此,不! 你不能访问私有方法,但这是一个解决方法。

在unit testing理论中,只有合同应该被testing。 即只有class级的公共成员。 但实际上开发人员通常要testing内部成员。 – 这并不坏。 是的,这是违背理论的,但在实践中有时可能是有用的。

所以如果你真的想testing内部成员,你可以使用这些方法之一:

  1. 让你的会员公开。 在许多书籍中,作者认为这种方法很简单
  2. 你可以让你的成员内部并添加InternalVisibleTo来安装
  3. 您可以使类成员受到保护,并从testing课下inheritancetesting类。

代码示例:

 public class SomeClass { private int SomeMethod() {} } [TestFixture] public class TestClass : SomeClass{ [Test] private void SomeMethodTest() {} }