我需要为下一个函数编写一个单元测试,我看到我可以使用[ExpectedException]
这是要测试的功能。
public static T FailIfEnumIsNotDefined<T>(this T enumValue, string message = null)
where T:struct
{
var enumType = typeof (T);
if (!enumType.IsEnum)
{
throw new ArgumentOutOfRangeException(string.Format("Type {0} is not an Enum, therefore it cannot be checked if it is Defined not have defined.", enumType.FullName));
}
else if (!Enum.IsDefined(enumType, enumValue))
{
throw new ArgumentOutOfRangeException(string.Format("{1} Value {0} is not does not have defined value in Enum of type {0}. It should not be...", enumType.FullName, message ?? ""));
}
return enumValue;
}
这里将使用代码来测试应该抛出的异常
[TestMethod]
[ExpectedException(ArgumentOutOfRangeException(ArgumentException), "message")]
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum()
{
// PREPARE
// EXECUTE
// ASSERT
}
我不知道必须为例外做出断言。
答案 0 :(得分:22)
ExpectedException
只是声明测试方法会抛出指定类型的异常:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum()
{
// PREPARE
// EXECUTE
// NO ASSERT!!
}
如果要声明其他异常参数,则应在测试方法中使用try..catch
:
[TestMethod]
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum()
{
// PREPARE
try
{
// EXECUTE
Assert.Fail()
}
catch(Exception exception)
{
// ASSERT EXCEPTION DETAILS
}
}
您可以编写自己的断言异常的方法,以避免一遍又一遍地重复相同的测试代码:
public TException AssertCatch<TException>(Action action)
where TException : Exception
{
try
{
action();
}
catch (TException exception)
{
return exception;
}
throw new AssertFailedException("Expected exception of type " +
typeof(TException) + " was not thrown");
}
用法:
var exception = AssertCatch<ArgumentOutOfRangeException>(() => /* EXECUTE */);
Assert.AreEqual("foo", exception.Message);
答案 1 :(得分:2)
您必须以不同方式使用ExpectedException
:
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void MyTestSomething()
然后对您的测试进行编码,以便抛出预期的异常。
答案 2 :(得分:1)
使用正确的异常消息断言异常抛出:
var ex = Assert.Throws<Exception>(() => _foo.DoSomething(a, b, c));
Assert.That(ex.Message, Is.EqualTo("Your exception message"));
答案 3 :(得分:1)
虽然ExpectedException
不能用于验证异常的消息,但您可以通过继承ExpectedExceptionBaseAttribute
来实现自己的异常验证逻辑:
通过实施您自己预期的异常验证。您可以 指定内置的附加信息和要求 ExpectedExceptionAttribute类的方法无法处理,例如 以下内容:
- 验证异常的状态。
- 期待多种类型的例外。
- 在抛出错误类型的异常时显示自定义消息。
- 控制阴性测试的结果。
在您的情况下,它可能看起来像这样:
public sealed class ExpectedExceptionMessageAttribute<T> : ExpectedExceptionBaseAttribute
{
readonly string _expectedMessage;
public ExpectedExceptionMessageAttribute(string expectedMessage)
{
_expectedMessage = expectedMessage;
}
protected override void Verify(System.Exception exception)
{
// Handle assertion exceptions from assertion failures in the test method
base.RethrowIfAssertException(exception);
Assert.IsInstanceOfType(exception, typeof(T), "wrong exception type");
Assert.AreEqual(_expectedMessage, exception.Message, "wrong exception message");
}
}
HAving说,我仍然倾向于使用直接try
- catch
方法,因为它更具体地说明了预期会抛出异常的位置:
public static void Throws<T>(Action action, Predicate<T> predicate = null)
where T : Exception
{
try
{
action();
}
catch (T e)
{
if (predicate == null || predicate(e))
{
return;
}
Assert.Fail($"Exception of type {typeof(T)} thrown as expected, but the provided predicate rejected it: {e}");
}
catch (Exception e)
{
Assert.Fail($"Expected exception of type {typeof(T)} but a different exception was thrown: {e}");
}
Assert.Fail($"No exception thrown, expected {typeof(T)}");
}
答案 4 :(得分:0)
如果您使用ExpectedException属性,则不需要断言,实际上您的代码不应该能够到达断言。
如果你想确保抛出异常,你应该在应该抛出异常的操作之后放置一个Assert.Fail(),在这种情况下,如果没有抛出异常,测试将会失败。