检查单元测试中是不是抛出参数

Posted

技术标签:

【中文标题】检查单元测试中是不是抛出参数【英文标题】:Checking if argument is thrown in unit-tests检查单元测试中是否抛出参数 【发布时间】:2012-02-03 09:56:55 【问题描述】:

我正在为一个应用程序进行单元测试,该应用程序具有一个将三个值作为参数的构造函数。数字应为 0 或更高,现在我正在为构造函数编写单元测试,如果不是这种情况,则会引发异常。

我不知道如何在“断言”之后写什么来确定这一点,以便在将非法数字传递给构造函数时测试通过。提前致谢。

编辑:我正在使用 MSTest 框架

   public void uniqueSidesTest2()
    
        try 
            Triangle_Accessor target = new Triangle_Accessor(0, 10, 10);
        
        catch ()
            Assert // true (pass the test)
            return;
        

        Assert. // false (test fails)
    

// 来自代码...

    public Triangle(double a, double b, double c) 
        if ((a <= 0) || (b <= 0) || (c <= 0))
            throw new ArgumentException("The numbers must higher than 0.");
        
        sides = new double[]  a, b, c ;
    

【问题讨论】:

我不确定在沼泽标准 MS 测试中,但在 NUnit 中你会注释测试以期待异常。您仍然会收到错误,但它不算作失败,例如ExpectedException(typeof(ArgumentException))] 与***.com/questions/933613/…重复 【参考方案1】:

如果您没有 nunit(或其他内置此支持的框架,您可以使用以下类型的辅助方法

 public static void ThrowsExceptionOfType<T>(Action action) where T: Exception
    
        try
        
            action();
        
        catch (T)
        
            return;
        
        catch (Exception exp)
        
            throw new Exception(string.Format("Assert failed. Expecting exception of type 0 but got 1.", typeof(T).Name, exp.GetType().Name));
        

        throw new Exception(string.Format("Assert failed. Expecting exception of type 0 but no exception was thrown.", typeof(T).Name));
    

你的测试应该是这样的

AssertHelper.ThrowsExceptionOfType<ArgumentException>( 
    () => 
    
        new Triangle_Accessor(0, 10, 10);
    );

【讨论】:

这也是我的工作。我还使用了辅助方法的重载,该方法的输出参数设置为抛出的异常。如果需要,这可以让您检查异常。 public static void ThrowsException(out TException throwedException, Action action) where TException : Exception try action.Invoke(); // 如果没有抛出异常,则失败 Assert.Fail("Assert.ThrowsException failed - 没有抛出预期的异常:" + typeof(TException).ToString());抛出异常 = 空; catch (TException ex) throwException = ex; 【参考方案2】:

这可能不是最好的解决方案,但如果我正在测试以确保抛出异常,我将执行以下操作:

public void uniqueSidesTest2()

    try 
        Triangle_Accessor target = new Triangle_Accessor(0, 10, 10);
        Assert.Fail("An exception was not thrown for an invalid argument.");
    
    catch (ArgumentException ex)
        //Do nothing, test passes if Assert.Fail() was not called
    

由于您的构造函数调用应该引发错误,因此如果它到达第二行(Assert.Fail() 行),那么您就知道它没有正确地引发异常。

【讨论】:

您应该至少捕获适当的异常,否则如果抛出 any 异常并且不完全正确,您将成功。 非常正确,我只是想对我过去的工作方式进行基本解释,然后复制/粘贴他的代码。我会做一些编辑。感谢您的提醒。【参考方案3】:

首先,你应该抛出一个ArgumentOutOfRangeException 而不仅仅是一个ArgumentException

其次,您的单元测试应该期望抛出异常,如下所示:

[ExpectedException(typeof(ArgumentOutOfRangeException))]
public static void MyUnitTestForArgumentA()

    ...

因此,您需要创建单独的单元测试——每个参数一个——测试当参数超出范围时方法是否抛出正确的异常。

【讨论】:

谢谢!我已在代码中更改为 ArgumentOutOfRangeException,但是当我添加 [ExpectedException(typeof(ArgumentOutOfRangeException))] 时,我收到以下错误消息:“错误 3 找不到类型或命名空间名称‘ArgumentOutOfRangeException’(您是否缺少使用指令还是程序集引用?)”? 它在 System 命名空间中,所以如果你能找到 ArgumentException,你应该也会自动找到 ArgumentOutOfRangeException。你确定你的拼写 100% 正确吗? 另见msdn.microsoft.com/en-us/library/…。 您在类文件中是否碰巧缺少using System;?该异常位于 mscorlib.dll 和 System 命名空间中。【参考方案4】:

您没有提及您用于单元测试的框架,但我认为您正在寻找的内容类似于此处显示的内容:

http://www.nunit.org/index.php?p=exception&r=2.4

【讨论】:

【参考方案5】:

无需使用 try catch 块。使用 NUnit 或 MSTest 框架,您可以在测试方法声明中使用属性来指定您期望出现异常。

MSTest

 [TestMethod]
 [ExpectedException(typeof(ArgumentException))]
 public void uniqueSidesTest2()

【讨论】:

我建议不要使用该属性,因为您不知道哪个方法负责引发异常。 @Toni,请注意扩展,因为我没有遵循您的思路。我可能遇到的唯一问题是异常可能不够具体,方法名称不是很好,但这两个都是直接从问题继承的特征。但方法是合理的。 @AnthonyPegram 如果您使用 ExpectedException,您不知道测试中的哪一行引发了该异常。 Simple example。在该示例中,您不知道哪个方法引发了异常,因此即使错误的东西引发了异常,测试也可能通过。 @Toni,这不是一个有效的单元测试,它做的太多了,测试不止一件事。而且它也不能说明这里的情况,问题很明显只是测试构造函数。 @AnthonyPegram 我的例子很糟糕。我要说明的一点是,如果您使用 ExpectedException 属性,您将不知道是否从正确的方法引发了异常。您可能有一些设置,或者您正在测试一些特定的使用场景。并非每个单元测试都只测试单一方法。你是对的,在这种特殊情况下(仅测试构造函数) ExpectedException 使用有效。太多次了解它的人滥用它并每次都使用它,有时甚至在集成测试中使用它。【参考方案6】:

catch 中不需要 Assert(但您可能希望捕获更具体的异常,例如 ArgumentException)。

为了总是失败,有一个Assert.Fail。

【讨论】:

以上是关于检查单元测试中是不是抛出参数的主要内容,如果未能解决你的问题,请参考以下文章

单元测试

如何检查单元测试中的值是不是为nan?

Node.js的断言模块assert进行单元测试

Swift UI 测试,如何检查单元格是不是有图像视图

如何使用 Xcode 7 UI 测试检查表格视图中的单元格是不是可见?

如何检查是不是在单元测试中调用了 sync.WaitGroup.Done()