我正在处理几个异常,一旦处理就不会重新抛出它们。如何断言在我的单元测试中调用了异常。
4 回答
我要做的是Exception
为你的遗留代码创建一个自定义,并将你遗留的东西抛出的异常放入它的内部异常中。然后你总是可以吞下你的自定义异常以在你的主应用程序中忽略它们,但它们仍然会被抛出以进行单元测试。
例子:
try
{
//rubbish legacy code which will throw all kinds of exceptions
}
catch(Exception ex)
{
throw new CustomException(message: "something bad happened", innerException: ex);
}
然后通常您可以执行以下操作:
try
{
MethodWhichCallsRubbishLegacyStuffAndWillProbablyThrowException();
}
catch (CustomException c)
{
//do nothing or better yet - logging!
}
catch (Exception ex)
{
//handle potential exceptions caused elsewhere
}
现在,在您的单元测试中,您可以针对抛出的CustomException
或确实是特定的进行断言。InnerException
我做过这样的事情,不确定它是否是好的做法......
第一的:
[TestMethod]
public void MethodName_TestErrorMessage_When_SomeException()
{
// Arrange
const string ExpectedMessgae= "Error in Application ";
this.MockedInterface.Setup(x=>x.MethodCall()).Throws<SomeException>();
// Act
var result=this.Controller.Action() as JsonResult;
// Assert
Assert.AreEqual(ExpectedMessage, result.Data.ToString());
}
这只是一个示例,但通常如果您没有重新抛出异常并且它已在代码中处理,那么我们可以验证消息是否正确。但这也意味着至少您没有丢失代码中的堆栈跟踪并返回它。如果有人帮助我改进这一点,我将不胜感激。另一种方法是ExcpectedException
属性,不应为此处理异常。
根据您对问题的评论:
如果我的一条消息由于遗留应用程序接口而失败,我将向第一线支持发送电子邮件,这可能会引发我正在处理的许多不同的异常。如果我的测试断言异常已被抛出和处理,那就太好了。
处理此问题的最简洁方法是确保处理异常然后将它们作为电子邮件传递的代码将电子邮件接收器作为构造函数上的接口接收。
然后,您可以模拟电子邮件处理程序,将其传递给您的测试代码,并断言它被赋予了正确的异常类型。
像这样的东西:
public interface IExceptionEmailer {
void HandleGenericException( Exception e );
void HandleYourExceptionTypeA ( ExceptionTypeA e );
// ... continue with your specific exceptions
}
public class YourClassThatCatchesExceptions( ){
private IExceptionEmailer emailer;
public void TheMethodThatCatches ( ) {
try {
// actions
} catch ( ExceptionTypeA e ) {
this.emailer.HandleYourExceptionTypeA( e );
} catch ( Exception e ) {
this.emailer.HandleGenericException( e );
}
}
public YourClassThatCatchesExceptions( IExceptionEmailer emailer ) {
this.emailer = emailer;
}
}
那么你的测试类(假设 Moq 和 Xunit)将是:
public class GivenAnExceptionEmailer ( ) {
[Fact]
public void WhenYourSpecificActionHappens ( ) {
var emailer = new Mock<IExceptionEmailer>();
// ARRANGE the rest of your system here
var target = new YourClassThatCatchesExceptions( emailer.Object );
// do whatever ACTions needed here to make it throw
target.Whatever( );
// then ASSERT that the emailer was given correct type
// this will fail if the exception wasn't thrown or wasn't
// properly caught and handled.
emailer.Verify ( e =>
e.HandleYourExceptionTypeA ( It.IsAny<ExceptionTypeA>( )),
Times.Once( )
);
}
}
我尚未对此进行测试,因此您可能会发现语法问题,但是,这会隔离您的系统,以便您可以验证您在YourClassThatCatchesExceptions
火灾中所期望的确切行为(并且您的管理员会感谢您没有向他们发送大量测试电子邮件! )
为什么要关心代码之外的人是否会看到它?我不会对不向调用者公开的此类功能进行单元测试。