我写了一个单元测试,它应抛出AnException
或AnotherException
,两者都来自AnExceptionBaseException
。然后我继续为基本异常添加ExpectedExceptionAttribute
,但却发现我的测试仍然会被标记为失败。
测试名称:Call_Should_Throw_If_Device_Is_Not_Ready测试
...
结果消息:测试方法 DiskManagementTests.DiskFreeSpaceTests.Call_Should_Throw_If_Device_Is_Not_Ready 抛出异常System.IO.FileNotFoundException,但异常 期望System.IO.IOException。异常消息: System.IO.FileNotFoundException:设备尚未就绪。 (例外 来自HRESULT:0x80070015)
这似乎是一个合理的设计决策,因为在这种特殊情况下,异常是从HRESULT返回代码生成的。这使得几乎不可能确定将抛出哪个异常。至少不能没有从我的测试单元中复制代码逻辑...测试。
我的代码(我相信这可以抛出FileNotFound
或DirectoryNotFound
):
[TestMethod]
[ExpectedException(typeof(IOException))]
public void Call_Should_Throw_If_Device_Is_Not_Ready()
{
foreach (DriveInfo drive in DriveInfo.GetDrives().Where(drive => !drive.IsReady))
{
DiskFreeSpace diskFreeSpace = DiskManagement.GetDiskFreeSpace(drive.RootDirectory.FullName);
Assert.Fail("API call did not fail even though the drive reports that it is not ready.");
}
Assert.Inconclusive("All drives were ready. Try testing with an empty disc drive.");
}
我是否需要重新考虑编写单元测试的方式?
修改
毕竟支持此方案。它真正需要的是将AllowDerivedTypes
设置为true。
[TestMethod]
[ExpectedException(typeof(IOException), AllowDerivedTypes = true)]
public void Call_Should_Throw_If_Device_Is_Not_Ready()
{
// ...
}
答案 0 :(得分:1)
您可以创建自己的ExpectedException
属性,以检查抛出的异常是否继承了属性中定义的异常。
public sealed class MyExpectedException : ExpectedExceptionBaseAttribute
{
private Type _expectedExceptionBaseType;
public MyExpectedException(Type expectedExceptionType)
{
_expectedExceptionBaseType = expectedExceptionType;
}
protected override void Verify(Exception exception)
{
Assert.IsNotNull(exception);
Assert.IsTrue(exception.GetType().IsInstanceOfType(typeof(_expectedExceptionBaseType)) ||
exception.GetType().IsSubclassOf(typeof(_expectedExceptionBaseType)));
}
}
并将属性更改为您的测试:
[MyExpectedException(typeof(IOException))]