简体   繁体   中英

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_as.netmvc3testing_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);
}

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM