断言抛出了一个处理过的异常

时间:2013-07-03 15:50:20

标签: c# nunit moq

我正在处理几个例外情况,一旦处理完毕就不会重新抛出它们。 如何断言在我的单元测试中调用异常。

4 个答案:

答案 0 :(得分:0)

我要做的是为您的遗留代码创建自定义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进行断言。

答案 1 :(得分:0)

根据您在问题中的评论:

  

如果我的一条消息由于遗留应用程序界面而失败,我将向第一线支持发送电子邮件,这可能会引发我正在处理的许多不同的异常。我的测试断言抛出和处理异常会很好。

处理此问题最简洁的方法是确保处理异常然后将其作为电子邮件传递的代码将电子邮件作为构造函数的接口接收。

然后,您可以模拟电子邮件处理程序,将其传递给您正在测试的代码,并断言它被赋予了正确的异常类型。

这样的事情:

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中所期望的确切行为会触发(并且您的管理员会感谢您不要用一堆测试电子邮件向他们发送垃圾邮件!)

答案 2 :(得分:0)

我做过这样的事情,不确定它的良好做法......

首先:

[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属性,不应该为此处理异常。

答案 3 :(得分:-1)

为什么关心你的代码以外的人会不会看到它?我不会对未向呼叫者公开的此类功能进行单元测试。