C# 在本例中,Microsoft对每个测试执行多个断言是否正确?

C# 在本例中,Microsoft对每个测试执行多个断言是否正确?,c#,unit-testing,C#,Unit Testing,最近,我一直在努力改进我的单元测试,UT的一个真正让我困惑的“规则”是“每个测试一个断言” 我很想知道人们是否认为MS在断言这个测试方面做了正确的事情(忽略缺乏模拟等)。根据我目前的理解,这个示例实际上应该为每个需要测试的对象属性执行一个创建调用(而不是一个调用和多个断言)。我的假设正确吗 方法取自: “按版本”类似于(为相册对象上的每个属性复制) [TestMethod()] public void CreateTest_AlbumUrl() { //**安排 var storeDB=new

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

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

方法取自:

“按版本”类似于(为相册对象上的每个属性复制)

[TestMethod()]
public void CreateTest_AlbumUrl()
{
//**安排
var storeDB=new Mock()
//一些设置模拟存储的代码会出现在这里
StoreManagerController目标=新的StoreManagerController(storeDB);
相册=新相册()
{
GenreId=1,
ArtistId=1,
Title=“新专辑”,
价格=10,
AlbumArtUrl=“/Content/Images/placeholder.gif”
};
//**法案
实际=目标。创建(相册);
var newAlbum=storeDB.Albums.SingleOrDefault(a=>a.AlbumId==album.AlbumId);
//**断言
Assert.AreEqual(album.AlbumArtUrl、newAlbum.AlbumArtUrl);
}

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


每个测试都应该测试一个故事/案例,但这可能需要多个断言来验证。我认为,仅仅为了满足一个“规则”而创建多个几乎相同的测试是过分的。但这只是我个人的观点。我更喜欢务实,而不是坚持书本上的规则。

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


每个测试都应该测试一个故事/案例,但这可能需要多个断言来验证。我认为,仅仅为了满足一个“规则”而创建多个几乎相同的测试是过分的。但这只是我个人的观点。我更喜欢务实,而不是遵守书本上的规则。

你不应该按照字面上的规则去做,你应该在每个测试中只声明一个行为,但是你可能需要有几个
assert
调用来声明一个行为


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

您不应该严格遵守该规则,您应该在每个测试中只断言一个行为,但您可能需要多次
断言
调用才能仅断言一个行为


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

这条规则经常被误解。它不是关于单个断言(如代码行中的断言),而是关于验证单个概念。在本例中,Microsoft验证是否正确添加了相册-相册在这里是单一概念

:

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


这条规则经常被误解。它不是关于单个断言(如代码行中的断言),而是关于验证单个概念。在本例中,Microsoft验证是否正确添加了相册-相册在这里是单一概念

:

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


谢谢,我认为这个评论比我读过的一些文章要清楚得多。谢谢,我认为这个评论比我读过的一些文章要清楚得多。每个测试用例应该只有一个断言。每个测试用例应该只有一个断言。
[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);
}