0

This is a follow up on this:

other SO post

Is this a good way to test whether the validation based on DataAnnotations works in the controller:

[Test]
public void UserController_CannotCreateUserWithNoLastName()
{
    // Arrange
    var user = new CreateUserViewModel();
    UsersController controller = new UsersController();
    var validationContext = new ValidationContext(user, null, null);
    var validationResults = new System.Collections.Generic.List<ValidationResult>();
    Validator.TryValidateObject(user, validationContext, validationResults);
    foreach (var validationResult in validationResults)
    {
    controller.ModelState.AddModelError("", validationResult.ErrorMessage);
    }

    // Act
    var result = controller.CreateUser(user);

    // Assert
    Assert.IsFalse(controller.ModelState.IsValid);
}

Any improvement suggestions would be very much welcome. I am also wondering whether one usually writes one test for each validation/business rule. Thanks!

Community
  • 1
  • 1
cs0815
  • 16,751
  • 45
  • 136
  • 299

1 Answers1

0

Is the code you listed based off of what's found here?

Personally, I write tests like so on a per annotation basis:

    [Test]
    public void CreateEventViewModel_Description_Property_Contains_StringLength_Attribute()
    {
        // Arrange
        PropertyInfo propertyInfo = typeof(CreateEventViewModel)
                                       .GetProperty("Description");
        // Act
        StringLengthAttribute attribute = propertyInfo
                      .GetCustomAttributes(typeof(StringLengthAttribute), true)
            .Cast<StringLengthAttribute>()
            .FirstOrDefault();

        // Assert
        Assert.NotNull(attribute);
        Assert.AreEqual(255, attribute.MaximumLength);
    }

I based this off of some information that Brad Wilson posted some time back. These tests are stored separate of the controller tests. I'm not sure if there's a more efficient way of doing this today (some folks have created more generic helper methods to do this type of testing; I just prefer having explicit tests for each attribute on my own) but it will verify that your data annotations do exist on your view models as expected.

A combination of this type of test, specifically verifying attributes, along with tests to test model state as listed in your previous question

UsersController.ModelState.AddModelError("username", "Bad username"); 

is what I typically go with.

Khepri
  • 9,547
  • 5
  • 45
  • 61
  • Thanks. What you wrote makes sense and yes my code is inspired by the link you mention in your first question. Your testing is very fine grained. Do you reckon what I am doing is wrong - see the controller method as a unit where I pass in viewmodels that violate certain business rules? You would have to write tests to check your controller whereas I wouldn't. Any feedback welcome ... – cs0815 Jun 23 '11 at 08:08
  • I don't necessarily see anything wrong with it. What you have above isn't testing any one specific state or expected error (that's one thing I'd like to point out looking at the test method title; are you *sure* that's all it's testing? It could be doing a lot more). It's looking at everything. Personally, I want specific tests to test each individual annotation or possible error state, but if you're comfortable with a slightly more generic test routine, that works as well. – Khepri Jun 23 '11 at 14:22