在开始之前,我是 AutoFixture 的忠实粉丝,我仍在学习如何使用该工具。因此,感谢开发 Autofixture 先生 Ploeh 和所有贡献者。
那么让我们从我的问题开始吧。
根据 AutoFixture/AutoMoq 忽略注入的实例/冻结模拟
上面链接的有趣部分给出了这段代码
Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);
ISettings settings = settingsMock.Object;
fixture.Inject(settings);
可以将其重写为 Mark 的答案
fixture.Freeze<Mock<ISettings>>()
.Setup(s => s.Get(settingKey)).Returns(xmlString);
它看起来像一个语法糖,使用 Freeze 方法是一种在流畅的界面中编写模拟的创建、配置和在 autofixture 容器中注入的方法。
在网上做了一些研究之后,Freeze 和 Inject 之间实际上存在功能差异。我发现了这个问题: https ://github.com/AutoFixture/AutoFixture/issues/59 这指向了 如何在 AutoFixture 中冻结空实例的答案
上述链接的作者将 Freeze 方法描述如下:
在内部,Freeze 创建一个请求类型的实例(例如 IPayPalConfiguration),然后注入它,这样当您再次请求它时,它总是会返回该实例
我明白当我们这样做时
var customer = fixture.Freeze<Order>();
每当我们的代码请求 Order 类型时,它将始终使用相同的 Order 实例。但是,如果我在 Freeze 构造函数中指定我希望它使用特定实例怎么办?
这是一个小代码示例:
[Fact]
public void MethodeName()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
fixture.Freeze<OrderLine>(new OrderLine("Foo"));
var order = fixture.Create<Order>();
}
public class Order
{
private readonly OrderLine _line;
public Order(OrderLine line)
{
_line = line;
}
}
public class OrderLine
{
private readonly string _name;
public OrderLine(string name)
{
_name = name;
}
}
OrderLine 的名称不应该等于“Foo”而不是 namefe48163a-d5a0-49a5-b349-7b11ba5f804b 吗?Freeze 方法的文档说:
<typeparam name="T">The type to freeze.</typeparam>
<param name="fixture">The fixture.</param>
<param name="seed">Any data that adds additional information when creating the anonymous object. Hypothetically, this value might be the value being frozen, but this is not likely.</param>
为什么作者不确定何时返回值?如果我在 Freeze 的构造函数中指定我的实例,我希望 autofixture 使用这个实例?
然后
请注意,除非您已自定义执行此操作,否则不太可能将其用作冻结值。如果您希望将特定值注入到 Fixture 中,则应使用该方法。`
看来我必须自定义种子参数。谁能澄清一下?文档指出的解决方案是使用 Inject 方法。事实上,它适用于我的 OrderLine 代码示例。
我正在寻求您的帮助,以了解 Freeze、Inject 和 Register 之间的区别,根据源代码,它只是由 Inject 方法调用,但它需要一个 lambda。