传递给Mock的参数干净地[单独验证调用之外]验证了许多属性?

时间:2012-07-16 19:52:22

标签: c# mocking moq

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而不创建多个测试?我认为能够捕获传递给mock的参数然后对其进行测试会很好,但是我还没有找到一种优雅的方法。

2 个答案:

答案 0 :(得分: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;     
   }
)));

您可以将断言移动到单独的方法以获得清晰度。

如果你想摆脱&#34;返回true;&#34;你可以为Action&lt; T&gt;写一个包装器返回一个Func&lt; T,bool&gt;总是返回true。这样你就可以写下以下内容:

saveThemeAS.Verify(service => service.Execute(FakeUserID, It.Is<LayoutENT.Theme>(ReturnsTrue(CheckTheme))))

答案 1 :(得分:1)

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

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) 
等等......