测试引发失败的功能

时间:2020-03-05 18:38:55  来源:igfitidea点击:

测试引发故障的功能的最佳方法是什么?还是测试一个完全可以避免故障的功能?

例如;我有一个" I / O完成端口"类,如果无法正确初始化端口,则会抛出该构造函数。它使用初始化程序列表中的CreateIoCompletionPort的Win32函数。如果未正确设置句柄的非null值,则构造函数将引发异常。我从未见过此功能失败。

我非常确定,如果它们(以及代码中的其他函数)失败,它们将正确运行,该代码为50行,包括空格,因此我的问题是

a)是否值得测试是否会抛出
b)如果值得测试,该怎么做?
c)是否应该对这些简单的包装器类进行单元测试?

对于b),我考虑了重写CreateIoCompletionPort并将值传递给。在单元测试中,请重写它,并在传入某个值时使它返回0。但是,由于在构造函数中使用了它,因此它必须是静态的。这看似有效还是无效?

解决方案

回答

测试失败条件绝对是值得的,既可以在类中适当地抛出异常,又可以在类中正确处理异常。

如果我们要对传递给构造函数的对象进行操作,则可以轻松完成此操作……只需传递一个模拟即可。如果没有,我倾向于将功能转移到受保护的方法,并覆盖受保护的方法以唤起我的失败案例。我将以Java为例,但是将思想移植到Ccase应该足够容易:

public class MyClass {
    public MyClass() throws MyClassException {
        // Whatever, including a call to invokeCreateIoCompletionPort
    }

    protected int invokeCreateIoCompletionPort(String str, int i) {
        return StaticClass.createIoCompletionPort(str, i);
    }
}

public class MyTest {
    public void myTest() {
        try {
            new MyClass();
            fail("MyClassException was not thrown!");
        } catch (MyClassException e) {
        }
    }

    private static class MyClassWrapper extends MyClass {
        @Override
        protected int invokeCreateIoCompletionPort(String str, int i) {
            throw new ExpectedException();
        }
    }
}

如我们所见,很容易测试正在测试的构造函数或者方法是否抛出了异常,并且还很容易从可以抛出异常的外部类中注入异常。抱歉,我没有使用实际方法,我只是使用该名称来说明听起来像我们在使用它,以及如何测试我们想测试的情况。

基本上,通常可以测试我们公开的任何API详细信息,并且如果我们想知道特殊情况可以正常工作,则可能需要对其进行测试。

回答

我们应该考虑以可以模拟I / O完成端口的方式编写代码。创建一个接口/抽象类,以暴露我们在I / O对象上所需的方法,并编写和测试实现应具有的功能的实现(以及可能模拟故障的选项)。

AFAIK的一种常见做法是在单元测试时模拟外部资源,以最大程度地减少依赖性。

回答

如果在.NET中执行此操作,则可以将ExpectedException属性添加到测试中:

[Test, ExpectedException(typeof(SpecificException), "Exception's specific message")]
public void TestWhichHasException()
{
    CallMethodThatThrowsSpecificException();
}

如果抛出该类型的异常并带有指定的消息,则测试将通过。该属性还有其他重载,包括具有InnerExceptions等。