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

最近我一直在努力改进我的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() // 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); } 

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

Roy Osherove用非常简单的话说 :

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

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

应该在每个测试中测试单个故事/案例,但这可能需要多个断言来validation。 恕我直言,创建多个几乎相同的测试只是为了满足“规则”是有点过分。 但这只是我个人的意见。 我更倾向于坚持书本规则。

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

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