在此示例中,Microsoft是否有权在每个测试中执行多个断言?

时间:2012-04-11 10:22:02

标签: c# unit-testing

最近我一直在努力改进我的单元测试,并且真正让我感到困惑的UT的“规则”之一是“每次测试的一个断言”。

我很想知道人们是否认为MS在断言这个测试方面做了正确的事情(忽略缺乏模拟等)。根据我目前的理解,这个例子应该真正执行一个需要测试的每个对象属性的创建调用(而不是一个调用和多个断言)。我做出这个假设是否正确?

方法取自: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);
            }
    }

版本将类似于(复制相册对象上的每个属性)

    [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);
}

3 个答案:

答案 0 :(得分:6)

这条规则经常被误解。它不是关于单个断言(如代码行/ Assert调用),而是关于验证单个概念。在这种情况下,Microsoft验证了相册是否正确添加 - 相册是单一概念。

Roy Osherove's put it in very simple words

  

我的指南通常是每次测试测试一个逻辑CONCEPT。你可以在同一个对象上有多个断言。它们通常与被测试的概念相同。

答案 1 :(得分:2)

这应该不是一个严格的规则,至多是一个经验法则。恕我直言,在许多情况下,将多个断言放入单个测试中会更简单,更容易。

应该在每个测试中测试单个故事/案例,但这可能需要多个断言来验证。恕我直言,创建多个几乎完全相同的测试只是为了满足&#34;规则&#34;。但这只是我个人的意见。我更倾向于坚持书本规则。

答案 2 :(得分:0)

你不应该从字面上理解这个规则,你应该只为每个测试断言一个行为,但你可能需要进行几次Assert调用来断言一个行为。

在这种情况下,测试中的行为似乎是使用提供的信息创建相册。