【问题标题】:AutoFixture and fluent Moq syntaxAutoFixture 和流畅的 Moq 语法
【发布时间】:2015-06-30 22:15:48
【问题描述】:

我使用 Moq 已经有一段时间了,为了简洁起见,我经常使用 Mock.Of... 的流畅语法来表达设置。

var foo = Mock.Of<IFoo>(f => f.Method(It.IsAny<string>()) == 7 && f.Property == "Hi");
var sut = new Whatever(foo);

最近,我开始使用 AutoFixture,但似乎找不到任何等效的语法来一次表达多个设置。我知道我可以使用Freeze 来表达同样的意思...

var foo = fixture.Freeze<Mock<IFoo>>();
foo.Setup(f => f.Method(It.IsAny<string>()).Returns(7);
foo.Setup(f => f.Property).Returns("Hi");
var sut = fixture.Create<Whatever>();

...但如果可能的话,我想获得自动模拟的好处,并保持流畅的起订量设置的简洁性。抛开风格上的争论不谈,AutoFixture 是否公开了让我流利地表达这些设置的任何方式?如果没有,我可以使用任何优化来使 AutoFixture 设置更简洁吗?

【问题讨论】:

  • 你考虑过使用 NSubstitute 吗?它比 Moq显着清洁 OOTB(也有一个 AutoNSubstitute 胶水库),所以如果你没有显着的不可忽视的沉没成本,你除了括号外什么都不会损失 :)
  • @RubenBartelink,在这种情况下,特别是我正在公司环境中使用基于 10k+ Moq/NUnit 的测试,因此可能不太可能切换框架。但是,对于我的个人项目,我肯定会看一下它(我可以在网上找到的少数比较非常人为,并将 NSubstitute 与非常“罗嗦”的非流利的 Moq 语法进行了比较,所以我必须做一个进行一些研究并自己尝试一下)。

标签: c# .net unit-testing moq autofixture


【解决方案1】:

您可以使用 Moq 的 fluent API 自己创建模拟,然后将其注入到夹具中:

var foo = Mock.Of<IFoo>(f => f.Method(It.IsAny<string>()) == 7 && f.Property == "Hi");
fixture.Inject(foo);

var sut = fixture.Create<Whatever>();

如果您使用的是AutoMoqCustomization,那么上面的代码将与您发布的代码执行相同的操作,除了不设置CallBase = trueDefaultValue = DefaultValue.Mock;

如果您使用AutoConfiguredMoqCustomization,则此代码不会设置任何其他成员,而自定义会设置。如果你想获得AutoConfiguredMoqCustomization 的好处使用 Moq 的 fluent API,恐怕这是不可能的。

【讨论】:

  • 不错。如果您在我的答案中包含帮助程序和/或合并,我将删除我的,因为要了解的关键是自动配置被Inject 淘汰,正如您所说。
  • @RubenBartelink 我不想偷你的学分,让我们保留两个答案;)
  • @dcastro,谢谢 - 这回答了我的问题。我希望它以某种方式直接烘焙到Freeze 或其他方法之一,这样我就可以减少额外的Mock.Of&lt;T&gt; 引入的噪音。我已经使用辅助方法(扩展和实例)来清理它,因此您的答案和 Ruben 的辅助方法就足够了。我正在使用AutoMoqCustomization,所以Inject 的使用应该不是问题。再次感谢。
【解决方案2】:

引用@dcastro 的答案,一个小包装器,其中包含与那里相同的警告:-

public static T SetMock<T>(this IFixture that, Expression<Func<T, bool>> expr)
    where T : class
{
    var mocked = Mock.Of(expr);
    that.Inject(mocked);
    return mocked;
}

允许您:

fixture.SetMock<IFoo>(f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi");

或者,如果您对具体值感兴趣:

var foo = fixture.SetMock<IFoo>(f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi");

没有助手的最干净的 C# 是:

fixture.Inject( Mock.Of<IFoo>( f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi")));

如果你是doing your tests in F#,使用Foq,你可以这样写:

Mock<IFoo>.With(fun x ->
    <@  x.Method(any()) --> 7
        x.Property --> "Hi" @>)
|> fixture.Inject

--&gt; 右侧的表达式只是代码,即您可以将算法内容放入其中,然后在编写时进行智能感知和类型检查)。或者(仍然使用 Foq):

fixture.Inject <|
    Mock<IFoo>.With(fun x -> <@  
        x.Method(any()) --> 7
        x.Property --> "Hi" @>)

或者(假设接口可以完全实现)您可以使用 F# 对象表达式:

fixture.Inject { new IFoo with 
    member x.Method _ = 7 
    member x.Property with get() = "Hi" }

【讨论】:

    猜你喜欢
    • 2015-02-17
    • 2011-08-12
    • 1970-01-01
    • 2019-09-03
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    相关资源
    最近更新 更多