Autofixture: (可选)禁用 AutoMoq 缓存?

创建于 2016-05-20  ·  14评论  ·  资料来源: AutoFixture/AutoFixture

使用 AutoConfiguredMoqCustomization 时,使用的fixture 返回的值会被缓存,并且每次调用都会返回相同的值(我不确定这是在 MockType.ReturnsUsingContext 还是其他地方完成的,但我看到了关于它的评论在第 104 行)。

我发现覆盖它的唯一方法是将有问题的模拟的 Frozen 实例传递到测试方法中,并使用调用夹具的 func 覆盖设置:

someMock.Setup(it => it.SomeMethodReturningAString()).Returns(() => fixture.Create<string>())

除了手动设置每次调用之外,是否有任何更通用/更智能的方法来配置自动生成的模拟以在每次需要来自 AutoFixture 的值时调用夹具?

enhancement good first issue

最有用的评论

我承认我认为测试替身被配置为回调 AutoFixture 以获得返回值。 AutoFixture 确实已经有一个生命周期管理机制(通过它的 Freeze 功能),所以我觉得AutoConfiguredMoqCustomization实现了自己的生命周期管理器,从而覆盖了 AutoFixture 本身提供的控制表面,这有点令人惊讶。

所有14条评论

缓存结果值背后的想法是让所有方法默认为_pure_ ,这被认为是一种很好的做法。

如果被测系统期望得到一个纯函数,但得到一个不纯函数,则测试很可能会导致误报。 例如

// This method will return the expected result *if* `GetInt` is pure.
int Double(IDependency dep) {
    return dep.GetInt() + dep.GetInt();
}

Assert.Equal(dep.GetInt * 2, Double(dep));

另一方面,如果被测系统不假设纯度,那么给它一个纯函数或不纯函数应该没有区别。

因此,当我实现这个特性时,默认使用纯函数对我来说是有意义的。

除了手动设置每次调用之外,是否有任何更通用/更智能的方法来配置自动生成的模拟以在每次需要来自 AutoFixture 的值时调用夹具?

如果您需要为 _one_ 方法执行此操作,但在多个测试中,我会将其放入可重用的IConfiguration

如果您想在多个测试中对所有方法执行此操作,则需要做更多工作:

我们也可以想办法使这种行为可配置,但我不确定需求是否足够高来证明这一点。 在我看来,这种改变不应掉以轻心——细粒度的定制可能会导致意外的复杂性。 @ploeh ,您对此有何看法?

我承认我认为测试替身被配置为回调 AutoFixture 以获得返回值。 AutoFixture 确实已经有一个生命周期管理机制(通过它的 Freeze 功能),所以我觉得AutoConfiguredMoqCustomization实现了自己的生命周期管理器,从而覆盖了 AutoFixture 本身提供的控制表面,这有点令人惊讶。

这是一个很好的观点,我从来没有这么想过Freeze 。 现在改变自定义的行为将是一个突破性的改变,我相信......你认为它应该在 AutoFixture v4 中改变吗?

这是我们记录的行为还是在测试中以某种方式“承诺”的行为?

令人惊讶的是,没有。 我很确定我已经涵盖了这一点,但似乎我没有。 至少我找不到任何涵盖此内容的测试,并且删除该行不会导致任何测试失败。 但是,IMO,它仍然是可观察到的行为,并且可能存在依赖于此的代码......

有道理。 是否可以是我们现在设置为一个值的配置值,然后在我们过渡到 AutoFixture 4 时切换它?

同意。 在这种情况下,“配置值”究竟是什么意思? 将它提升到MockType类中的 const 就足够了吗? 例如, private const bool cacheReturnValues = true然后是if(cacheReturnValues) /**/

我承认,这有点随随便便的评论,所以我不知道如果没有太多更改,这是否可行。 不过,我的意思是:

@andreasnilsen现在想改变这种行为,但我们担心这会是一个突破性的改变。 如果我们使行为可配置,那么我们现在就给@andreasnilsen一种改变行为的方法,同时我们不会破坏任何其他客户端。

当我们引入 AutoFixture 4 时,我们更改了默认配置,因此默认行为是不缓存返回值。 或者我们可能只是删除该选项......

像布尔值cacheReturnValues可能是一种方法,但我们必须让客户端能够更改值,所以它不能是private

(此外,除非我们绝对确定只有两个值,否则我们应该考虑使用enum而不是bool 。)

啊,我一开始以为你指的是一些在 v4 中很容易发现和更改的内部标志。

想到的前两种方法是:

  • 只需向AutoConfiguredMoqCustomization的构造函数添加一个布尔参数(可选,为了向后兼容),然后将其向下传播到MockVirtualMethodsCommand和内部MockType.ReturnsUsingContext 。 这似乎:

    1. 有点复杂和

    2. 也_ad hoc_。 如果我们想在自定义中添加更多配置参数,构造函数将变得过于复杂且难以使用/维护。

  • 使用参数对象模式来解决上面的问题 (ii)。

我对做出我们可能会后悔并在以后陷入困境的设计决策持谨慎态度,因此我们将非常感谢您维护该项目的专业知识/经验。

我在想类似策略的东西......

啊,是的,当然! 我想我专注于“配置值”而忘了退后一步。

我很抱歉迟到的回复,我已经被淹没了 - 我很快就会看看这个,然后回来提出一个设计方案。

最近,我们执行了自定义重构以使用属性进行自定义调整。 潜在地,可以像下面这样控制此功能(找到更好的设置名称):
c# new AutoMoqCustomization { CacheCallResults = false }

在幕后,我们可以通过不同的策略来实现,就像上面建议的那样。

使用标签跳转进行标记,因为实现这一点应该相对简单。

@zvirja你能帮我一下吗,我可以解决这个问题。 我只是不知道从哪里开始:)

@micheleissa感谢您的关注! 我建议只阅读AutoMoq源代码并调试它以了解内部机制。 它非常小,所以应该不会花太多时间......

如果您有更具体的问题,请询问😉

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

mjfreelancing picture mjfreelancing  ·  4评论

Ridermansb picture Ridermansb  ·  4评论

JoshKeegan picture JoshKeegan  ·  6评论

joelleortiz picture joelleortiz  ·  4评论

tiesmaster picture tiesmaster  ·  7评论