我正在使用NUnit 3.0编写一些单元测试,与v2.x不同,ExpectedException()
已从库中删除。
根据this的答案,我绝对可以看到试图捕捉测试中的一个逻辑,他们希望他们的系统能够抛出异常(而不仅仅是在测试的任何地方说出来' ;)
但是,我倾向于非常清楚我的Arrange,Act和Assert步骤,这使它成为一个挑战。
我曾经做过类似的事情:
[Test, ExpectedException(typeof(FormatException))]
public void Should_not_convert_from_prinergy_date_time_sample1()
{
//Arrange
string testDate = "20121123120122";
//Act
testDate.FromPrinergyDateTime();
//Assert
Assert.Fail("FromPrinergyDateTime should throw an exception parsing invalid input.");
}
现在我需要做一些事情:
[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
//Arrange
string testDate = "20121123120122";
//Act/Assert
Assert.Throws<FormatException>(() => testDate.FromPrinergyDateTime());
}
这并不可怕,但在我看来,这个法案和断言都是混乱的。 (显然,对于这个简单的测试,它并不难理解,但在更大的测试中可能更具挑战性。)
我有一位同事建议我完全摆脱Assert.Throws
,只做以下事情:
[Test]
public void Should_not_convert_from_prinergy_date_time_sample3()
{
//Arrange
int exceptions = 0;
string testDate = "20121123120122";
//Act
try
{
testDate.FromPrinergyDateTime();
}
catch (FormatException) { exceptions++;}
//Assert
Assert.AreEqual(1, exceptions);
}
在这里,我坚持严格的AAA格式,但代价是更加臃肿。
所以我的问题出现在AAA风格的测试人员身上:你会如何进行某种异常验证测试,就像我在这里尝试一样?
答案 0 :(得分:58)
我知道你来自哪里,即使我不介意在这种情况下结合Act / Assert步骤。
我唯一能想到的是将实际的委托(此处为FromPrinergyDateTime
)存储到变量中作为&#34; act&#34;步骤然后断言:
[Test]
public void Should_not_convert_from_prinergy_date_time_sample2()
{
//Arrange
string testDate = "20121123120122";
//Act
ActualValueDelegate<object> testDelegate = () => testDate.FromPrinergyDateTime();
//Assert
Assert.That(testDelegate, Throws.TypeOf<FormatException>());
}
我得到了&#34;行为&#34;步骤不是真正行动,而是定义行动是什么。但是,它确实清楚地描述了正在测试的行动。
答案 1 :(得分:19)
答案 2 :(得分:6)
您可以在NUnit 3中创建自定义属性。以下是如何创建[ExpectedException]属性的示例代码。(ExpectedExceptionExample显示如何为NUnit实现自定义属性) https://github.com/nunit/nunit-csharp-samples