断言私有方法的例外

时间:2012-05-15 15:16:32

标签: c# exception nunit assert private-methods

我使用NUnit在C#中对私有方法进行单元测试。

例如,我的方法(如果是公共的)应该抛出ArgumentNullException。我可以断言该方法会抛出ArgumentNullException,如此:Assert.Throws<ArgumentNullException>(() => method.Call());

但是,由于我使用反射调用私有方法,因此我会为抛出TargetInvocationException的方法声明ArgumentNullException,如下所示:Assert.Throws<TargetInvocationException>(() => methodInfo.Invoke(obj, new object[] { params }));

我想为该私有方法声明一个ArgumentNullException而不是TargetInvocationException,这样我就可以扫描它的代码,知道它应该做什么而不是调试来查找。

我如何断言实际的异常,而不是TargetInvocationException

注意: 这个问题并没有解决单元测试公共与私人方法背后的理论。我和我的团队决定对私有方法进行单元测试,这是否是单元测试的方式与这个问题无关。请参阅this问题上最受欢迎的答案,了解我们的理由。

3 个答案:

答案 0 :(得分:6)

找到我的答案:

var exception = Assert.Throws<TargetInvocationException>(() => methodInfo.Invoke(obj, new object[] { params }));
Assert.IsInstanceOf<Exception>(exception.InnerException);

<强>更新

Assert.IsNotNull(exception.InnerException)让我知道存在内部异常。 Assert.IsInstanceOf<Exception>(exception.InnerException);将断言任何类型的Exception抛出。我同意两种方式都告诉我们存在内部异常。

然而.....如果我想断言特定类型的内部异常怎么办?

例如,如果我的方法抛出ArgumentNullException,那么通过执行Assert.IsInstanceOf<FileNotFoundException>(exception.InnerException);我无法断言使用Assert.IsNotNull让我知道存在内部异常,但它没有揭示内部异常的类型。因此,这就是我更喜欢在这种情况下使用IsInstanceOf的原因。

答案 1 :(得分:2)

在Assert上创建一个扩展方法,即带有func的“ThrowsInnerException”,使用Try / Catch包装并抛出InnerException(在您的情况下,对应于ArgumentNullException)

以下是一段代码(未经测试&amp; 无法编译,因为我在没有编辑器的情况下键入它,但它应该会给你一个想法)

public static class AssertExtension 
    {
        public static void ThrowsInnerException<T>(Action action) 
        {
            Assert.Throws<T>(delegate() {
                try { action(); }
                catch (Exception exc) { throw exc.InnerException; }
            });
        }
    }

答案 2 :(得分:0)

您确定单元测试私有方法是个好主意吗?因为听起来不像。

最好测试调用私有方法的公共方法。

<强>更新

更重要的是,尽管我没有看到你的代码,但我认为最好将参数验证放到公共方法并测试它们。

<强> UPDATE2
发现非常相似的SO question

<强> UPDATE3
我在类似案例中使用的方法(用于模拟private字段)只是将private方法标记为internal并添加InternalsVisibleTo(<assembly_with_unit_tests>)属性被测装配。
这不是一个好主意(实际上我反对这个,当它在团队设计会议上提出时,因为它不对,不纯,等等),但结果却为编写单元测试节省了大量时间。