当注入两个具体实例时,第二个实例会覆盖第一个实例。
当注入一个具体实例,然后是一个模拟实例时,第二个实例不会覆盖第一个实例。
这使得执行一些使用模拟的测试和一些使用实现的测试(使用测试类构造函数在测试之间共享夹具)的想法相当笨拙。
当注入两个具体实例时,第二个实例会覆盖第一个实例。
当注入一个具体实例,然后是一个模拟实例时,第二个实例会覆盖第一个实例。
```C#
使用 System.Collections.Generic;
使用 AutoFixture;
使用 AutoFixture.AutoMoq;
使用最小起订量;
使用 Xunit;
命名空间 SomeNamespace
{
公共类 AutoFixtureTests
{
[事实]
// 通过
public void Should_OverridePreviouslyInjectedString()
{
const string test1 = "test1";
const string test2 = "test2";
var fixture = new Fixture();
fixture.Inject(test1);
fixture.Inject(test2);
Assert.Equal(fixture.Create<string>(), test2);
}
[Fact]
// Fails
public void Should_OverridePreviouslyInjectedInstance()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var sut1 = new List<int>();
fixture.Inject<IList<int>>(sut1);
fixture.Freeze<Mock<IList<int>>>();
var sut2 = fixture.Create<IList<int>>();
Assert.NotSame(sut1, sut2);
}
}
}
``
嗨@charles-salmon,
感谢您抽出时间报告此事。
您观察到的行为是_by design_。 请允许我解释一下。 🙂
如果你看一下执行的的Freeze<T>
方法:
var value = fixture.Create<T>();
fixture.Inject(value);
return value;
你会看到它所做的只是创建一个T
的样本并将它注入到夹具中。 实际上, Freeze
方法是作为此操作的便捷快捷方式出现的。 正如@ploeh在 2010 年介绍 Freeze 方法的帖子中所写:
事实证明,我们如此频繁地使用这种编码习惯用法,以至于我们决定将其封装在一种方便的方法中。 经过一番讨论,我们得出了 Freeze 这个名字,因为我们基本上冻结了夹具中的一个匿名变量,绕过了创建新实例的默认算法。
鉴于此,冻结与注入实例相同的类型T
产生相同的实例也就不足为奇了。
现在,要解决您的问题:
这使得执行一些使用模拟的测试和一些使用实现的测试(使用测试类构造函数在测试之间共享夹具)的想法相当笨拙。
鉴于夹具代表测试运行的 _context_,您当然可以_让多个测试共享同一个夹具; 然而,这是以混合多个(可能是相互冲突的)问题为代价的。
xUnit Patterns 一书很好地总结了它:
Shared Fixture的最大问题是它可能导致测试之间的“冲突”,这可能导致Erratic Tests ,因为测试可能取决于其他测试的结果。 另一个问题是,设计用于多个测试的夹具肯定比单个测试所需的最小夹具复杂得多。
当一个测试期望T
类型的对象是一个特定实例,而另一个测试期望T
是一个假对象时,就会发生这种“冲突”。
由于我想不出一个测试场景,其中相同类型的T
既是模拟 _ 又是具体实例(尽管我很高兴被证明是错误的),我建议你有这些测试使用不同的装置,每个装置都被配置为服务于它们的特定场景。
最有用的评论
嗨@charles-salmon,
感谢您抽出时间报告此事。
您观察到的行为是_by design_。 请允许我解释一下。 🙂
如果你看一下执行的的
Freeze<T>
方法:你会看到它所做的只是创建一个
T
的样本并将它注入到夹具中。 实际上,Freeze
方法是作为此操作的便捷快捷方式出现的。 正如@ploeh在 2010 年介绍 Freeze 方法的帖子中所写:鉴于此,冻结与注入实例相同的类型
T
产生相同的实例也就不足为奇了。现在,要解决您的问题:
鉴于夹具代表测试运行的 _context_,您当然可以_让多个测试共享同一个夹具; 然而,这是以混合多个(可能是相互冲突的)问题为代价的。
xUnit Patterns 一书很好地总结了它:
当一个测试期望
T
类型的对象是一个特定实例,而另一个测试期望T
是一个假对象时,就会发生这种“冲突”。由于我想不出一个测试场景,其中相同类型的
T
既是模拟 _ 又是具体实例(尽管我很高兴被证明是错误的),我建议你有这些测试使用不同的装置,每个装置都被配置为服务于它们的特定场景。