AutoFixture 和流畅的 Moq 语法
AutoFixture and fluent Moq syntax
我已经使用 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>();
...但如果可能的话,我想获得自动模拟的好处,并保持流畅的 Moq 设置的简洁性。除了风格上的争论,AutoFixture 是否为我提供了任何方式来流利地表达这些设置?如果没有,我可以使用任何优化来使 AutoFixture 设置更简洁吗?
您可以使用 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 = true
和 DefaultValue = DefaultValue.Mock;
。
如果您使用 AutoConfiguredMoqCustomization
,则此代码不会设置任何其他成员,而自定义会。想要坐收AutoConfiguredMoqCustomization
和的好处,就用Moq的fluentAPI,恐怕不行。
模仿@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#, with Foq,你会写成:
Mock<IFoo>.With(fun x ->
<@ x.Method(any()) --> 7
x.Property --> "Hi" @>)
|> fixture.Inject
(-->
右边的表达式只是代码,即你可以把算法的东西放在那里,你在写的时候会得到智能感知和类型检查)。或者(仍然使用 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" }
我已经使用 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>();
...但如果可能的话,我想获得自动模拟的好处,并保持流畅的 Moq 设置的简洁性。除了风格上的争论,AutoFixture 是否为我提供了任何方式来流利地表达这些设置?如果没有,我可以使用任何优化来使 AutoFixture 设置更简洁吗?
您可以使用 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 = true
和 DefaultValue = DefaultValue.Mock;
。
如果您使用 AutoConfiguredMoqCustomization
,则此代码不会设置任何其他成员,而自定义会。想要坐收AutoConfiguredMoqCustomization
和的好处,就用Moq的fluentAPI,恐怕不行。
模仿@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#, with Foq,你会写成:
Mock<IFoo>.With(fun x ->
<@ x.Method(any()) --> 7
x.Property --> "Hi" @>)
|> fixture.Inject
(-->
右边的表达式只是代码,即你可以把算法的东西放在那里,你在写的时候会得到智能感知和类型检查)。或者(仍然使用 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" }