gpt4 book ai didi

c# - 无法掌握 Freeze/Inject/Register 之间的区别

转载 作者:IT王子 更新时间:2023-10-29 03:55:36 26 4
gpt4 key购买 nike

开始之前,我是 AutoFixture 的忠实粉丝,我仍在学习如何使用该工具。因此,感谢 Ploeh 先生和所有贡献者开发了 Autofixture。

那么让我们从我的问题开始吧。

根据 AutoFixture/AutoMoq ignores injected instance/frozen mock

上面链接中有趣的部分给出了这段代码

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 方法是一种在流畅的界面中编写模拟创建、配置和自动修复容器注入(inject)的方法。

在网络上做了一些研究后,Freeze 和 Inject 之间实际上存在功能差异。我发现了这个问题: https://github.com/AutoFixture/AutoFixture/issues/59哪一点的答案 How can I Freeze a null instance in AutoFixture

上面链接的作者描述卡住方法如下:

Internally, Freeze creates an instance of the requested type (e.g. IPayPalConfiguration) and then injects it so it will always return that instance when you request it again

我明白当我们这样做的时候

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 吗?卡住方法的文档说:

<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 使用这个实例?

然后

Please notice that the isn't likely to be used as the frozen value, unless you've customized to do this. If you wish to inject a specific value into the Fixture, you should use the method instead.`

看来我必须自定义种子参数。谁能澄清一下?文档指出的解决方案是使用 Inject 方法。事实上,它在我的 OrderLine 代码示例中有效。

我正在寻求您的帮助,以了解 Freeze、Inj​​ect 和 Register 之间的区别,根据源代码,后者仅由 Inject 方法调用,但它需要一个 lambda。

最佳答案

注册和注入(inject)

曾几何时,没有Inject没有 Freeze ; Register控制代码。

那时候,有一个Register重载定义如下:

public static void Register<T>(this IFixture fixture, T item)

但是,它必须与这个近亲共享 API:

public static void Register<T>(this IFixture fixture, Func<T> creator)

AutoFixture 的创建者认为这很好,但遗憾的是:用户感到困惑。最糟糕的是,用户可以写:

fixture.Register(() => universe.LightUp());

还有

fixture.Register(universe.LightUp);

意思完全一样,因为universe.LightUp是对方法的引用,因此与委托(delegate)匹配。

但是,该语法看起来像一个属性引用,所以如果 LightUp如果是属性而不是方法,编译器将选择第一个重载。

这引起了很多困惑,所以 Register<T>(this IFixture fixture, T item)重载重命名为 Inject<T>(this IFixture fixture, T item) .

卡住

卡住有不同的历史。很久以前,当我还在以命令式的方式使用AutoFixture时,我注意到我反复写这样的代码:

var foo = fixture.Create<Foo>();
fixture.Inject(foo);

所以我决定这是一个概念,并将其命名为卡住Freeze method 只是这两行代码的简写。

I'm looking for your help to understand the difference between Freeze, Inject, and also Register which, according to the source code, is just called by Inject method but it takes a lambda

一般来说,区分Inject应该不难。和 Register ,因为他们的签名不会冲突。因此,如果您尝试使用这两种方法中的一种来实现目标,并且您的代码可以编译,那么您可能选择了正确的版本。

对于 Freeze 也是如此如果不是因为 OP 中使用的过载:

[EditorBrowsable(EditorBrowsableState.Never)]
public static T Freeze<T>(this IFixture fixture, T seed)

注意这个重载实际上有 EditorBrowsableState.Never ,因为它总是让人们感到困惑。然而,尽管如此,显然人们仍然发现过载,所以我认为 it should be moved in AutoFixture 4 .它是存在的功能之一,因为它易于实现...

关于c# - 无法掌握 Freeze/Inject/Register 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18161127/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com