C# CodeOverage与ExpectedException
我对这种模式进行了几个单元测试:C# CodeOverage与ExpectedException,c#,unit-testing,expected-exception,C#,Unit Testing,Expected Exception,我对这种模式进行了几个单元测试: [TestMethod ()] [ExpectedException (typeof (ArgumentNullException))] public void DoStuffTest_Exception () { var foo = new Foo (); Foo.DoStuff (null); } 事实证明,代码覆盖率将抛出行标记为半运行,因此每次我得到1块未覆盖的代码 在考虑这个问题一段时间后,我能想到的最佳解决方案是添加一个try/ca
[TestMethod ()]
[ExpectedException (typeof (ArgumentNullException))]
public void DoStuffTest_Exception ()
{
var foo = new Foo ();
Foo.DoStuff (null);
}
事实证明,代码覆盖率将抛出行标记为半运行,因此每次我得到1块未覆盖的代码
在考虑这个问题一段时间后,我能想到的最佳解决方案是添加一个try/catch。因为这是一个重复的模式,所以我将沿着
public static void ExpectException<_T> (Action action) where _T: Exception
{
try { action(); }
catch (_T) { return; }
Assert.Fail ("Expected " + _T);
}
publicstaticvoidexpectexception(Action-Action),其中_T:Exception
{
试试{action();}
catch(_T){return;}
Assert.Fail(“预期”+\T);
}
这将有一个好处,我可以将所有异常测试添加到非抛出测试中
这是一个有效的设计,还是我错过了什么
编辑:Ugs。。。似乎上面的ExpectException方法也给我留下了1个未覆盖的块。是的,这是相当标准的费用-我们的许多测试都是这样做的。同时,你不得不怀疑你是否对代码覆盖率有太高的评价,如果这些分支的分量如此之大,那么它就值得付出努力。你的建议是正确的。除了代码覆盖率问题之外,我认为它比使用
ExpectedException
属性要好,因为它明确显示了预期哪一行测试会抛出异常。使用ExpectedException
意味着测试中的任何代码行都可以抛出预期的异常类型,并且测试仍然会通过。如果错误源于另一个不希望抛出的调用,那么它可以掩盖这样一个事实,即测试应该失败,因为应该抛出的行不是
对您建议的内容进行有用的修改是返回捕获的异常:
public static _T ExpectException<_T> (Action action) where _T: Exception
{
try { action(); }
catch (_T ex) { return ex; }
Assert.Fail ("Expected " + typeof(_T));
return null;
}
[TestMethod]
public void my_test()
{
ExpectException<InvalidOperationException>(delegate()
{
throw new ArgumentException("hello");
});
}
@adrianbanks如果操作参数引发的异常与预期异常不同,则ExpectException不会按预期工作:
public static _T ExpectException<_T> (Action action) where _T: Exception
{
try { action(); }
catch (_T ex) { return ex; }
Assert.Fail ("Expected " + typeof(_T));
return null;
}
[TestMethod]
public void my_test()
{
ExpectException<InvalidOperationException>(delegate()
{
throw new ArgumentException("hello");
});
}
[TestMethod]
公共无效my_测试()
{
ExpectException(委托()
{
抛出新的ArgumentException(“hello”);
});
}
当我执行TestMethod“my_test”时,我刚刚收到一条消息,说测试方法引发了System.ArgumentException:hello。在这种情况下,它应该说“预期的无效操作异常”。
我为ExpectException方法提出了一个新版本:
public static void VerifierException<T>(Action action) where T : Exception
{
try
{
action();
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(T));
return;
}
Assert.Fail("Aucune exception n'a été déclenchée alors qu'une exception du type " + typeof(T).FullName + " était attendue");
}
publicstaticvoidverifierexception(Action-Action),其中T:Exception
{
尝试
{
动作();
}
捕获(例外情况除外)
{
IsInstanceOfType(例如,typeof(T));
返回;
}
Assert.Fail(“Aucune exception n'aétédéclenchée alors qu'une exception du type”+typeof(t.FullName+“était attendue”);
}
我知道这是一个老话题,但我遇到了同样的问题
最后我问自己:为什么我需要知道测试的覆盖范围<我不知道-所以让我们排除它们,这样覆盖范围更干净
在我的测试项目中,我添加了一个CodeCoverage.runsettings
文件,内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<RunSettings>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Configuration>
<CodeCoverage>
<ModulePaths>
<Exclude>
<ModulePath>.*tests.dll</ModulePath>
<ModulePath>.*Tests.dll</ModulePath>
<!-- Add more ModulePath nodes here. -->
</Exclude>
</ModulePaths>
</CodeCoverage>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
*tests.dll
*Tests.dll
选择此测试设置文件后,我的代码覆盖率为100%
这样就不需要“黑客”单元测试代码覆盖率系统,只为了达到100%:-)目前覆盖率高达可怕的35%,所以这不会增加太多。这更多的是一个小的设计问题(可能会节省几百行测试代码)。+1。好东西。这个问题困扰了我一段时间,但我一直没有时间去解决它。谢谢你的这个想法!我目前无法亲自尝试,但这似乎是一个非常好的解决方案,如果你只是确保测试本身是正确的。