user460667
user460667

Reputation: 1940

Is Microsoft right to be performing multiple asserts per test in this example?

Recently I have been trying to improve my unit tests and one of the 'rules' of UT that really confuses me is the 'one assert per test'.

I am interested to know whether people think MS have done the right thing in regards to asserting this test (ignore the lack of mocks, etc). Based on my current understanding, this example should really be performing one creation calls per object property that needs to be tested (instead of one call and multiple asserts). Am I correct in making this assumption?

Method taken from: http://msdn.microsoft.com/en-us/vs2010trainingcourse_aspnetmvc3testing_topic4

[TestMethod()]
    [DeploymentItem("MvcMusicStore.mdf")]
    [DeploymentItem("MvcMusicStore_log.ldf")]
    public void CreateTest()
    {
            using (TransactionScope ts = new TransactionScope())
            {
                StoreManagerController target = new StoreManagerController();
                Album album = new Album()
                {
                    GenreId = 1,
                    ArtistId = 1,
                    Title = "New Album",
                    Price = 10,
                    AlbumArtUrl = "/Content/Images/placeholder.gif"
                };
                ActionResult actual;
                actual = target.Create(album);
                Assert.IsTrue(album.AlbumId != 0);
                MusicStoreEntities storeDB = new MusicStoreEntities();
                var newAlbum = storeDB.Albums.SingleOrDefault(a => a.AlbumId == album.AlbumId);
                Assert.AreEqual(album.GenreId, newAlbum.GenreId);
                Assert.AreEqual(album.ArtistId, newAlbum.ArtistId);
                Assert.AreEqual(album.Title, newAlbum.Title);
                Assert.AreEqual(album.Price, newAlbum.Price);
                Assert.AreEqual(album.AlbumArtUrl, newAlbum.AlbumArtUrl);
            }
    }

By version would be something like (replicated for each property on the album object)

    [TestMethod()]
    public void CreateTest_AlbumUrl()
    {
        // ** Arrange
        var storeDB = new Mock<MusicStoreEntities>()

        // Some code to setup the mocked store would go here

        StoreManagerController target = new StoreManagerController(storeDB);
        Album album = new Album()
           {
             GenreId = 1,
             ArtistId = 1,
             Title = "New Album",
             Price = 10,
             AlbumArtUrl = "/Content/Images/placeholder.gif"
            };

        // ** Act
        actual = target.Create(album);                      
        var newAlbum = storeDB.Albums.SingleOrDefault(a => a.AlbumId == album.AlbumId);

        // ** Assert
        Assert.AreEqual(album.AlbumArtUrl, newAlbum.AlbumArtUrl);
}

Upvotes: 1

Views: 190

Answers (3)

k.m
k.m

Reputation: 31484

This rule is way too often misunderstood. It's not about single assertion (as in line of code/ Assert call), but about verifying single concept. In this case, Microsoft verifies album was added correctly - album is single concept here.

Roy Osherove's put it in very simple words:

My guideline is usually that you test one logical CONCEPT per test. you can have multiple asserts on the same object. they will usually be the same concept being tested.

Upvotes: 6

Jo&#227;o Angelo
Jo&#227;o Angelo

Reputation: 57728

You should not be taking that rule literally, you should only assert one behavior per test, but you may need to have several Assert calls to assert just one behavior.

In this case the behavior under test seems to be that the album is created with the provided information.

Upvotes: 0

P&#233;ter T&#246;r&#246;k
P&#233;ter T&#246;r&#246;k

Reputation: 116306

That should not be a hard rule, at most a rule of thumb. IMHO in many cases it is simpler and easier to put multiple asserts into a single test.

One should test a single story / case in each test, but this may well require multiple asserts to verify. IMHO it is overkill to create multiple nearly identical tests only to satisfy a "rule". But this is just my personal opinion. I prefer being pragmatic over adhering to book rules.

Upvotes: 2

Related Questions