Nick Gallimore
Nick Gallimore

Reputation: 1263

Asserting that a system under test should throw an assertion exception

I am creating an extension method that performs a test on an object to see if it has a specific custom attribute.

I want to create a unit test for my extension method. How can I assert that the test in the extension method should fail?

[Test]
public void ShouldFailIfEmailAttributeMissingFromFieldName()
{
    //--Arrange
    var model = new { Field = 1 };

    //--Act
    model.ShouldValidateTheseFields(new List<FieldValidation>
    {
        new EmailAddressFieldValidation
        {
            ErrorId = 1,
            ErrorMessage = "Message",
            FieldName = nameof(model.Field)
        }
    });
    //--Assert

}

Basically, the ShouldValidateTheseFields does reflection and asserts that it should have a custom attribute on the field named "Field" and I need to assert that it failed.

Upvotes: 5

Views: 1092

Answers (2)

Nick Gallimore
Nick Gallimore

Reputation: 1263

Create a new custom exception and have it throw if it is missing the custom attribute:

    [Test]
    public void ShouldFailIfEmailAddressAttributeIsMissingFromFieldName()
    {
        //--Arrange
        var model = new { Field = 1 };

        //--Act
        Should.Throw<EmailAddressAttributeNotFoundException>(() => model.ShouldValidateTheseFields(
            new List<FieldValidation>
            {
                new EmailAddressFieldValidation
                {
                    ErrorId = 1,
                    ErrorMessage = "Message",
                    FieldName = nameof(model.Field)
                }
            }));
    }

To check if an assertion fails you need to catch the Assertion exception. In this case since the Shouldly Framework is being used, it is a Shouldly.ShouldAssertException which is being thrown in the extension method:

[Test]
public void ShouldFailIfEmailAddressAttributeHasWrongErrorId()
{

    //--Arrange
    var model = new TestModelTwo();

    //--Act
    Should.Throw<ShouldAssertException>(() => model.ShouldValidateTheseFields(
    new List<FieldValidation>
    {
        new EmailAddressFieldValidation
        {
            ErrorId = 2,
            ErrorMessage = "Message",
            FieldName = nameof(model.Field)
        }
    }));
}

Using the class:

public class TestModel
{
    [EmailAddress(1)]
    public string Field { get; set; }
}

The failing assertion in the extension method is ErrorId.ShouldBe(2) when it is actually 1 on the model.

Upvotes: 1

Nkosi
Nkosi

Reputation: 247323

Catch the expected exception. If none is thrown the test fails

[Test]
public void ShouldFailIfEmailAttributeMissingFromFieldName() {
    //--Arrange
    var model = new { Field = 1 };

    //--Act
    try {
        model.ShouldValidateTheseFields(new List<FieldValidation> {
            new EmailAddressFieldValidation {
                ErrorId = 1,
                ErrorMessage = "Message",
                FieldName = nameof(model.Field)
            }
        });
    } catch(MyExpectedException e) {
        return;
    }

    //--Assert
    Assert.Fail();
}

Depending on the test framework being used there should be a way for you to assert expected exceptions for a test, which would basically follow a similar format above under the hood.

Upvotes: 5

Related Questions