问题
How do I use Assert.Throws
to assert the type of the exception and the actual message wording.
Something like this:
Assert.Throws<Exception>(
()=>user.MakeUserActive()).WithMessage("Actual exception message")
The method I am testing throws multiple messages of the same type, with different messages, and I need a way to test that the correct message is thrown depending on the context.
回答1:
Assert.Throws
returns the exception that's thrown which lets you assert on the exception.
var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));
So if no exception is thrown, or an exception of the wrong type is thrown, the first Assert.Throws
assertion will fail. However if an exception of the correct type is thrown then you can now assert on the actual exception that you've saved in the variable.
By using this pattern you can assert on other things than the exception message, e.g. in the case of ArgumentException
and derivatives, you can assert that the parameter name is correct:
var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));
You can also use the fluent API for doing these asserts:
Assert.That(() => foo.Bar(null),
Throws.Exception
.TypeOf<ArgumentNullException>()
.With.Property("ParamName")
.EqualTo("bar"));
A little tip when asserting on exception messages is to decorate the test method with the SetCultureAttribute
to make sure that the thrown message is using the expected culture. This comes into play if you store your exception messages as resources to allow for localization.
回答2:
You can now use the ExpectedException
attributes, e.g.
[Test]
[ExpectedException(typeof(InvalidOperationException),
ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
MethodA(null);
}
回答3:
Assert.That(myTestDelegate, Throws.ArgumentException
.With.Property("Message").EqualTo("your argument is invalid."));
回答4:
This is an old yet relevant question with outdated answers so I'm adding the current solution:
public void Test() {
throw new MyCustomException("You can't do that!");
}
[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
var exception = Assert.ThrowsException<MyCustomException>(
() => Test(),
"This should have thrown!");
Assert.AreEqual("You can't do that!", exception.Message);
}
This works with using Microsoft.VisualStudio.TestTools.UnitTesting;
回答5:
To expand on persistent's answer, and to provide more of the functionality of NUnit, you can do this:
public bool AssertThrows<TException>(
Action action,
Func<TException, bool> exceptionCondition = null)
where TException : Exception
{
try
{
action();
}
catch (TException ex)
{
if (exceptionCondition != null)
{
return exceptionCondition(ex);
}
return true;
}
catch
{
return false;
}
return false;
}
Examples:
// No exception thrown - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => {}));
// Wrong exception thrown - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new ApplicationException(); }));
// Correct exception thrown - test passes.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException(); }));
// Correct exception thrown, but wrong message - test fails.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException("ABCD"); },
ex => ex.Message == "1234"));
// Correct exception thrown, with correct message - test passes.
Assert.IsTrue(
AssertThrows<InvalidOperationException>(
() => { throw new InvalidOperationException("1234"); },
ex => ex.Message == "1234"));
回答6:
It's a long time since this issue was raised, I realize, but I recently ran into the same thing, and suggest this function for MSTest:
public bool AssertThrows(Action action) where T : Exception
{
try {action();}
catch(Exception exception)
{
if (exception.GetType() == typeof(T)) return true;
}
return false;
}
usage:
Assert.IsTrue(AssertThrows<FormatException>(delegate{ newMyMethod(MyParameter); }));
More here: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/
回答7:
Since I'm disturbed by the verbosity of some of the new NUnit patterns, I use something like this to create code that is cleaner for me personally:
public void AssertBusinessRuleException(TestDelegate code, string expectedMessage)
{
var ex = Assert.Throws<BusinessRuleException>(code);
Assert.AreEqual(ex.Message, expectedMessage);
}
public void AssertException<T>(TestDelegate code, string expectedMessage) where T:Exception
{
var ex = Assert.Throws<T>(code);
Assert.AreEqual(ex.Message, expectedMessage);
}
The usage is then:
AssertBusinessRuleException(() => service.Create(content), "Name already exists");
来源:https://stackoverflow.com/questions/1609536/how-do-i-use-assert-throws-to-assert-the-type-of-the-exception