1
saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(savedTheme => 
            savedTheme != null
            && savedTheme.Name == FakeCopiedThemeName
            && savedTheme.ThemeID == 0
            && savedTheme.WidgetSkins.Any(skin => skin.Name == FakeWidgetSkinName && skin.WidgetSkinID == 0)
            && savedTheme.SiteStyles.Any(style => style.SiteStyleID == FakeStyleID && style.SiteStyleID == 0)
            )));

对模拟的预期调用至少一次,但从未执行过:

这里的基本问题是我只是失败了,但我不知道具体是什么失败/什么设置不正确,因为它可能是上述 5 个条件中的任何一个。

我想分别检查上面的每个条件。有没有一种巧妙的方法可以在不创建多个测试的情况下使用 Moq 做到这一点?我认为能够捕获传递给模拟的参数然后对其进行测试会很好,但我无法找到一种优雅的方式来做到这一点。

4

2 回答 2

5

本质上,您要求的是让您的内部 lambda 执行一系列断言,而不是简单地评估为布尔值。

所以让我们这样做:)

saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(savedTheme => 
   {
      Assert.IsNotNull(savedTheme);
      Assert.AreEqual(FakeCopiedThemeName, savedTheme.Name);
      Assert.AreEqual(0, savedTheme.ThemeID)

      etc...

      return true;     
   }
)));

为了清楚起见,您可以将断言移至单独的方法。

如果你想摆脱“return true;” 您可以为 Action<T> 编写一个包装器,它返回一个始终返回 true 的 Func<T,bool>。这样你就可以写一些类似的东西:

saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(ReturnsTrue(CheckTheme))))
于 2012-07-16T20:05:37.643 回答
1

我认为我解决这个问题的方法是在模拟设置中使用回调,以便回调保存传递给它的 savedTheme 对象的副本。然后我会在稍后的单元测试中执行断言。这保留了 AAA(排列、动作、断言)模式,并且看起来比将断言逻辑放入模拟设置更清晰。例如:

protected static LayoutENT.Theme savedTheme;
// Arrange
themeParam = null;
saveThemeAS.Setup(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>)
    .Callback<layoutENT.Theme>(p =>  savedTheme = p);

// Act
// Calls the subject under test

// Assert
Assert.IsNotNull(savedTheme); 
Assert.AreEqual(FakeCopiedThemeName, savedTheme.Name); 
Assert.AreEqual(0, savedTheme.ThemeID) 

ETC...

于 2012-07-17T23:15:44.320 回答