1

最近我一直在努力改进我的单元测试,而真正让我困惑的 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);
}
4

3 回答 3

6

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

Roy Osherove 用非常简单的话说

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

于 2012-04-11T10:28:11.637 回答
2

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

应该在每个测试中测试一个故事/案例,但这很可能需要多个断言来验证。恕我直言,创建多个几乎相同的测试只是为了满足“规则”是矫枉过正的。但这只是我个人的看法。我更喜欢务实而不是遵守书本规则。

于 2012-04-11T10:24:19.003 回答
0

您不应该从字面上理解该规则,您应该每次测试只断言一种行为,但您可能需要多次Assert调用才能断言一种行为。

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

于 2012-04-11T10:26:20.597 回答