4
\$\begingroup\$
[Test]
public void Post_ReturnsCorrectModel()
{
    var post = new Post
    {
        Slug = "continuing-to-an-outer-loop",
        Title = "Continuing to an outer loop",
        Summary = "When you have a nested loop, sometimes",
        Content = "When you have a nested loop, sometimes",
        PublishedAt = DateTime.Now.AddDays(7),
        Tags = new Collection<Tag> { new Tag { Name = "Programming" } }
    };

    repository.Setup(expression => expression.Find("continuing-to-an-outer-loop"))
              .Returns(post);

    var viewResult = (ViewResult) controller.Post("continuing-to-an-outer-loop");
    var actual = viewResult.Model as PostViewModel;

    Assert.NotNull(actual);

    Assert.AreEqual(actual.Slug, post.Slug);
    Assert.AreEqual(actual.Title, post.Title);
    Assert.AreEqual(actual.Summary, post.Summary);
    Assert.AreEqual(actual.Content, post.Content);
    Assert.AreEqual(actual.PublishedAt, post.PublishedAt);
    Assert.AreEqual(actual.Tags, post.Tags);
}

Hopefully the purpose of this test is already clear but to further clarify - the repository exposes a Post object that is mapped to a PostViewModel. I then proceed to assert that the action method returns the correct model.

The action method looks like this:

public ActionResult Post(string slug)
{
    Post post =
        repository.Find(slug);

    if (post == null || post.Draft)
    {
        return HttpNotFound();
    }

    return View("Post", post.MapTo<PostViewModel>());
}

Could you please review this test? My particular areas of concern are as follows:

  • Is the test well named? (I adopted the name from here).
  • Must I assert that each property is equal as I have above? I feel as though I can make a reasonable assumption that if one property is equal then the rest will be too.
  • Here I am modelling the post object based on a real blog post. I do not think that the value of each property really matters and that I could very well have used arbitrary strings. Are there any best practices regarding which test data to use?
  • Would it be reasonable to extract the post object to another class and expose it using a factory of sorts? This will reduce the ceremony of my test and keep things DRY. Are there any best practices regarding this?
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$
  • I think the test is reasonably well named (imho).

  • If you assume you write the test against a black box (meaning you don't know how the controller code is implemented) then yes you should compare all properties. Someone could have forgotten to copy a property for example. This is especially the case for later when new properties get added (as a regression test). If you find yourself writing code like that a lot then there are several ways to automate this comparison.

  • I prefer to use human readable strings in unit tests. Makes it easier to read. However once you start doing integrations tests like hitting a test database you want to possibly generate some more exotic strings (non latin characters) to make sure that what you put into the db is also what you get back out and not some garbled nonsense. Some databases can be nasty in that regard.

  • If you find yourself creating the same post over and over again then you have some options:

    • If it's just inside one test fixture then create the post in the Setup routine.
    • If it's across multiple test fixtures then yes extract it into a test utility class.
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for your answer bud. As is the case with the other question of mine that you answered, I will mark your answer as accepted soon. I want to encourage additional answers. \$\endgroup\$ Commented Jul 27, 2014 at 21:52
2
\$\begingroup\$

I encourage any additional feedback.

Customize test messages. Without it one gets expected true. Was false and that's it. I like to know the expected & actual values without having to read test code. When running hundreds of tests this becomes essential, IMHO. Further, it has a self-documentation quality.

Assert.AreEqual(actual.Slug, post.Slug,
           string.Format("Wrong Slug. Expected: {0} Was: {1}",actual.Slug, post.Slug));

And overriding ToString can also be very helpful for testing feedback.

Would it be reasonable to extract the post object to another class and expose it using a factory of sorts? This will reduce the ceremony of my test and keep things DRY. Are there any best practices regarding this?

If you're wanting to encapsulate for the sake of testing per-se take a look at the NUnit CustomConstraint

\$\endgroup\$
1
  • \$\begingroup\$ You can use the overloaded Assert.AreEqual() like Assert.AreEqual(actual.Slug, post.Slug,"Wrong Slug. Expected: {0} Was: {1}",actual.Slug, post.Slug); this is doing the String.Fromat() by itself. \$\endgroup\$
    – Heslacher
    Commented Jul 28, 2014 at 11:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.