How do I enforce exception message with ExpectedException attribute

CRice picture CRice · Jan 17, 2011 · Viewed 32.9k times · Source

I thought these two tests should behave identically, in fact I have written the test in my project using MS Test only to find out now that it does not respect the expected message in the same way that NUnit does.

NUnit (fails):

[Test, ExpectedException(typeof(System.FormatException), ExpectedMessage = "blah")]
public void Validate()
{
    int.Parse("dfd");
}

MS Test (passes):

[TestMethod, ExpectedException(typeof(System.FormatException), "blah")]
public void Validate()
{
    int.Parse("dfd");
}

No matter what message I give the ms test, it will pass.

Is there any way to get the ms test to fail if the message is not right? Can I even create my own exception attribute? I would rather not have to write a try catch block for every test where this occurs.

Answer

BlackjacketMack picture BlackjacketMack · Jun 5, 2013

We use this attribute all over the place and we clearly misunderstood the second parameter (shame on us).

However, we definitely have used it to check the exception message. The following was what we used with hints from this page. It doesn't handle globalization, or inherited exception types, but it does what we need. Again, the goal was to simply RR 'ExpectedException' and swap it out with this class. (Bummer ExpectedException is sealed.)

public class ExpectedExceptionWithMessageAttribute : ExpectedExceptionBaseAttribute
{
    public Type ExceptionType { get; set; }

    public string ExpectedMessage { get; set; }

    public ExpectedExceptionWithMessageAttribute(Type exceptionType)
    {
        this.ExceptionType = exceptionType;
    }

    public ExpectedExceptionWithMessageAttribute(Type exceptionType, string expectedMessage)
    {
        this.ExceptionType = exceptionType;
        this.ExpectedMessage = expectedMessage;
    }

    protected override void Verify(Exception e)
    {
        if (e.GetType() != this.ExceptionType)
        {
            Assert.Fail($"ExpectedExceptionWithMessageAttribute failed. Expected exception type: {this.ExceptionType.FullName}. " +
                $"Actual exception type: {e.GetType().FullName}. Exception message: {e.Message}");
        }

        var actualMessage = e.Message.Trim();
        if (this.ExpectedMessage != null)
        {
            Assert.AreEqual(this.ExpectedMessage, actualMessage);
        }

        Debug.WriteLine($"ExpectedExceptionWithMessageAttribute:{actualMessage}");
    }
}