为什么调用 AutoFake.Provide() 会清除已经使用 A.CallTo() 配置的假货?

Why does calling AutoFake.Provide() wipe out fakes already configured with A.CallTo()?

为什么调用 fake.Provide<T>() 会清除已使用 A.CallTo() 配置的假货?这是一个错误吗?

我正在尝试了解我 运行 遇到的 Autofac.Extras.FakeItEasy(又名 AutoFake)问题。我有一个部分解决方案,但我不明白为什么我的原始代码不起作用。原代码比较复杂,为了这个问题,我花了一些时间简化了。

为什么这个测试失败了? (working DotNetFiddle)

public interface IStringService { string GetString(); }

public static void ACallTo_before_Provide()
{
    using (var fake = new AutoFake())
    {
        A.CallTo(() => fake.Resolve<IStringService>().GetString())
            .Returns("Test string");

        fake.Provide(new StringBuilder());
        
        var stringService = fake.Resolve<IStringService>();
        string result = stringService.GetString();

        // FAILS. The result should be "Test string",
        // but instead it's an empty string.
        Console.WriteLine($"ACallTo_before_Provide(): result = \"{result}\"");
    }
}

如果我交换对 fake.Provide<T>()A.CallTo() 的调用顺序,它会起作用:

public static void Provide_before_ACallTo()
{
    // Same code as above, but with the calls to
    // fake.Provide<T>() and A.CallTo() swapped
    using (var fake = new AutoFake())
    {
        fake.Provide(new StringBuilder());
        
        A.CallTo(() => fake.Resolve<IStringService>().GetString())
            .Returns("Test string");
        
        var stringService = fake.Resolve<IStringService>();
        string result = stringService.GetString();

        // SUCCESS. The result is "Test string" as expected
        Console.WriteLine($"Provide_before_ACallTo(): result = \"{result}\"");
    }
}

我知道发生了什么,有点,但我不确定这是故意行为还是错误。

发生的事情是,对 fake.Provide<T>() 的调用导致使用 A.CallTo() 配置的所有内容丢失。只要我总是在 fake.Provide<T>()之后调用A.CallTo() ,一切正常。

但我不明白为什么会这样。

  • 我在 the documentation 中找不到任何说明无法在 Provide<T>() 之前调用 A.CallTo() 的内容。
  • 同样,我找不到任何提示 Provide<T>() 不能与 A.CallTo() 一起使用的内容。

看来您配置无关依赖项的顺序无关紧要。

这是一个错误吗?或者这是预期的行为?如果这是预期的行为,有人可以解释为什么会这样吗?

不是Fake的配置被改了。在第一个测试中,Resolve 每次调用时都会 returning 不同的假货。 (检查它们的引用相等性;我做到了。)

Provide 创建一个新的 scope 并将其压入堆栈。 Resolve 在找到 return 的对象时使用最顶层的作用域。我认为这就是为什么你在 ACallTo_before_Provide.

中得到不同的假货

Is this a bug? Or is this the expected behavior? If this is the expected behavior, can someone explain why it works like this?

我不清楚。我不是 Autofac 用户,不明白为什么 Provide 引入了额外的作用域。 PR 18 中引入了堆叠作用域行为。或许作者可以解释一下原因。

与此同时,如果可能,我会 ProvideResolve 之前,如果你能做到的话,我会Provide 你需要的一切。