使用FakeItEasy,是否可以创建一个采用generics类型参数的虚拟对象

我有以下测试:

[Fact] public void StartProgram_CallsZoneProgramStart() { var zone = A.Fake(); zone.StartProgram(); A.CallTo(() => zone.ZoneProgram.Start(null, A.Dummy<ActionBlock>())).MustHaveHappened(Repeated.Exactly.Once); } 

它正在创建一个ActionBlock类型的虚拟对象,它被传递给MustHaveHappened调用。 zone.StartProgram肯定会调用zone.ZoneProgram.Start方法,但FakeItEasy看不到此调用。 它返回以下错误消息:

 Assertion failed for the following call: ZoneLighting.ZoneProgramNS.ZoneProgram.Start(, ActionBlock\`1 Id=1) Expected to find it exactly once but found it #0 times among the calls: 1: ZoneLighting.ZoneProgramNS.ZoneProgram.Start(inputStartingValues: Faked ZoneLighting.ZoneProgramNS.InputStartingValues, interruptQueue: ActionBlock`1 Id=2) 2: ZoneLighting.ZoneProgramNS.ZoneProgram.Start(inputStartingValues: , interruptQueue: ActionBlock`1 Id=2) 

从错误消息中可以看出,被比较的ActionBlocks上的ID是不同的(1和2),这就是为什么它无法看到调用的原因。 我的问题是,为什么dummied ActionBlock的ID = 1? 我认为它是一个虚拟对象,它不应该像ID等那样具有任何具体细节。这是因为generics类型不能被愚弄吗?

我在这里看到类似的东西: https : //github.com/FakeItEasy/FakeItEasy/issues/402

但我无法弄清楚这是不是在谈论同样的事情。 任何帮助将不胜感激。

我对ActionBlock不熟悉,所以我不确定他们从哪里得到他们的Id值,但我想我可以对你的测试中发生的事情有所了解。

首先,我认为你对Dummy是什么感到困惑。 如果是这样,不要感觉不好。 它们可能有点令人困惑。 从Dummy文档中 ,Dummy是

Dummy是FakeItEasy在需要某种类型的对象时可以提供的对象,但该对象的实际行为并不重要。

它们主要由FakeItEasy本身使用,当它需要创建一个对象来提供给类构造函数时(我们稍后会看到更多),或者当它需要从方法或属性返回一个不可伪造的对象时。 最终用户很少需要创建它们。

Dummy是一个真实的对象(它必须是 – 否则,我们怎么能用它做任何事情?)。 它必须具有其类型具有的任何具体细节(在本例中为ActionBlock )。 对Dummyinggenerics类型没有限制。

看看关于如何制作Dummy的文档,我们可以看到,因为ActionBlock可能没有可用的自定义IDummyDefinition (你有吗?),而且它不是一个Task,它不是可伪造的(因为class是密封的),然后通过调用一个ActionBlock构造函数来制作Dummy,并使Dummies使每个参数都满意。

我猜ActionBlocks有ID。 它们是如何分配的,我不知道,但如果它们是一个好的ID,那么看起来我们有两个不同的ActionBlock :一个在zone.StartProgram提供,而Dummy在测试中生成。

ActionBlocks文档表明它不会覆盖Equals ,因此将执行引用比较,并且两个ActionBlocks(Dummy和生产代码中使用的那个)不匹配。 这就是FakeItEasy无法识别通话的原因。

如果您只是试图查看是否使用第一个参数null和第二个参数对某个ActionBlock进行了对zone.ZoneProgram.Start调用,我认为您可能打算使用:

 A.CallTo(() => zone.ZoneProgram.Start(null, A>.Ignored)) .MustHaveHappened(Repeated.Exactly.Once); 

Ignored也可以缩短为_ 。如果您愿意,请阅读更多关于忽略参数值的信息 。)

虽然我对两件事情有所顾虑,但这可能会让你超越眼前的问题:

  1. 它看起来像zone.ZoneProgram.Start被调用两次,而不是“Exactly.Once”,但我相信你将能够处理这个,并且
  2. 通常,伪造被测物体被认为是反模式。 通常,一个虚拟依赖项提供给测试中的生产代码。 我并不是说它不会起作用,但有时会导致混乱。 在目前的问题得到解决之后,这可能是另一天的问题。

我希望有所帮助。

哦,你询问了问题402.这个问题是关于在定义控制假人如何创建的自定义类时给予用户更多的权力。 除非你创建了一个扩展IDummyDefinitionDummyDefinition的类, IDummyDefinition它可能不相关。