Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for multiple asserts on same result in C#

What do you think is cleanest way of doing multiple asserts on a result? In the past I've put them all the same test but this is starting to feel a little dirty, I've just been playing with another idea using setup.

[TestFixture]
public class GridControllerTests
{
    protected readonly string RequestedViewId = "A1";

    protected GridViewModel Result { get; set;}

    [TestFixtureSetUp]
    public void Get_UsingStaticSettings_Assign()
    {
        var dataRepository = new XmlRepository("test.xml");

        var settingsRepository = new StaticViewSettingsRepository();

        var controller = new GridController(dataRepository, settingsRepository);

        this.Result = controller.Get(RequestedViewId);

    }

    [Test]
    public void Get_UsingStaticSettings_NotNull()
    {
        Assert.That(this.Result,Is.Not.Null);
    }

    [Test]
    public void Get_UsingStaticSettings_HasData()
    {
        Assert.That(this.Result.Data,Is.Not.Null);
        Assert.That(this.Result.Data.Count,Is.GreaterThan(0));
    }

    [Test]
    public void Get_UsingStaticSettings_IdMatches()
    {
        Assert.That(this.Result.State.ViewId,Is.EqualTo(RequestedViewId));
    }

    [Test]
    public void Get_UsingStaticSettings_FirstTimePageIsOne()
    {
        Assert.That(this.Result.State.CurrentPage, Is.EqualTo(1));
    }
}
like image 521
asdseee Avatar asked Jan 14 '10 09:01

asdseee


People also ask

Can you have multiple asserts in one test?

you can have multiple asserts on the same object. they will usually be the same concept being tested.

Should you have one assert per test?

“One assertion per test” is a wise rule to keep in mind, because it helps you have tests that fail for a specific reason, and drives you to focus on a specific behavior at a time.

How many asserts should a unit test have?

One Assertion in One Test Method To keep unit tests simple, it is best to include a single assertion in one test method. That means, one unit test should test one use-case and no more.


2 Answers

Having multiple assertions in the same test can lead to Assertion Roulette, so this is something of which you should always be careful.

However, Assertion Roulette is mostly a problem when the assertions are unrelated. If they are conceptually closely related, many assertions can often be viewed as a single Logical Assertions.

In many cases you can get the best of both worlds by explicitly encapsulating such a Logical Assertion in a a custom type or method.

like image 170
Mark Seemann Avatar answered Oct 15 '22 08:10

Mark Seemann


What you need to keep to is the pattern of Arrange, Act, Assert (and then end the test). In your case all the arrangement is in the TestFixtureSetUp, as is the action being tested. I would re-arrange this a bit, it may become unwieldy when you have more tests. As Dockers notes, heavy test set-ups should be avoided, they can become problems - they are "one size fits all" across all tests in the class and so can become heavier than most of the tests need.

If you're tempted to carry on to another follow-on action and then more asserts, put this in a separate test.

I have no issue with putting multiple asserts in the same test, so long as they contribute to testing the same thing (i.e are part of the same "Logical Assertion"). In this case, any number of asserts on the contents of this.Result.Data would be OK by me - they would all inspect the same result value. Your Get_UsingStaticSettings_HasData does this very clearly. It's best to use a unique failure message on each assert so that it's easier to tell which assert failed.

Alternately, you could wrap up the related asserts in a single method. this is useful for the usual DRY reasons if you use it more than once, but otherwise I don't see that it's a big difference.

In Summary
* Do one action per test
* After the action, use as many related asserts as you need to test one thing
* End the test there.

like image 23
Anthony Avatar answered Oct 15 '22 10:10

Anthony