AutoFixture和流利的Moq语法

Sch*_*uNZ 4 .net c# unit-testing moq autofixture

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

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

最近,我开始使用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>();
Run Code Online (Sandbox Code Playgroud)

......但如果可能的话,我希望获得自动锁定的好处,并保持流畅的Moq设置的简洁性.除了文体论点,AutoFixture是否公开了任何方式让我能够流利地表达这些设置?如果没有,我可以使用任何优化来使AutoFixture设置更简洁吗?

dca*_*tro 5

您可以使用 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>();
Run Code Online (Sandbox Code Playgroud)

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

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

  • @RubenBartelink 我不想从你那里窃取学分,让我们保留两个答案;) (2认同)

Rub*_*ink 5

重温@ 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;
}
Run Code Online (Sandbox Code Playgroud)

允许您:

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

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

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

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

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

如果您正在使用Foq 在F#中进行测试,那么您可以将其写为:

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

(右边的表达式-->只是代码,即你可以在其中放入算法内容,并在编写时获得智能感知和类型检查).或者(仍然使用Foq):

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

或者(假设界面有意义完全实现)您可以使用F#对象表达式:

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