Rhino Mocks:实例化 Mock 属性,以便 Expectation 可以引用它
Posted
技术标签:
【中文标题】Rhino Mocks:实例化 Mock 属性,以便 Expectation 可以引用它【英文标题】:Rhino Mocks: Instantiating Mock property so Expectation can reference it 【发布时间】:2011-06-07 19:31:34 【问题描述】:我正在编写一个带有模拟的单元测试,但我无法成功编写它。其中一个属性是一个集合,我需要在为模拟设置期望时引用它。现在期望语句抛出一个空值。大致是这样的。
IFoo myMock = MockRepository.GenerateMock<IFoo>();
List<Entity> col = new List<Entity>();
Entity entity = new Entity();
myMock.Expect(p => p.FooCollection).Return(col);
myMock.Expect(p => p.FooCollection.Add(entity)); // throws null exception here
我是 rhino mocks 的新手,感觉我做的不对。还有其他方法可以正确实例化集合吗?可能没有我上面的期望?
更新 我认为我遇到了问题,因为我定义的接口将集合指定为只读。
interface IFoo
List<Entity> FooCollection get;
【问题讨论】:
【参考方案1】:我对 Rhino Mocks 并不太熟悉,但我认为在您致电 .Replay()
之前,您的期望并没有实际上挂钩 - 您在示例中暗示的模拟方法看起来更像Moq 给我。
也就是说,我认为您在这里做的事情根本上是错误的。你到底想测试什么?是p
对象,还是List<Entity>
上的某个对象?如果您真正想要测试的是p.YourMethodUnderTest()
实际将entity
添加到集合中,您可能只想设置p.FooCollection
以返回您的列表,然后验证您的列表是否包含实体对象。
// Arrange
IFoo myMock = MockRepository.GenerateMock<IFoo>();
List<Entity> col = new List<Entity>();
Entity entity = new Entity();
myMock.Expect(p => p.FooCollection).Return(col);
// myMock.Expect(p => p.FooCollection.Add(entity)) - skip this
// Act
p.YourMethodUnderTest(entity);
// Assert
Assert.IsTrue(col.Contains(entity)); // Or something like that
【讨论】:
我不知道为什么我没想到!我想我对 rhino mocks 的要求太多了。非常感谢您的解决方案。 @jlafay:很高兴我能帮上忙 =)【参考方案2】:您应该使用存根而不是模拟,例如:
IFoo myMock = MockRepository.GenerateStub<IFoo>();
myMock.FooCollection = col;
此外,您正在对一个真实对象 (collection.Add()) 设置期望,这实际上是行不通的。您可以通过将FooCollection
属性类型设置为IList
而不是具体的List
来解决此问题。
使用具体的集合类型作为参数无论如何都是一种代码味道(我建议使用 FxCop 来教你这些东西)。
【讨论】:
该集合是只读的,因此您不能像在示例中那样直接分配它。是否因为我将集合公开为属性而产生了代码异味?我可以看到将其保留为私有字段并添加 AddEntity() 方法是有益的,因为现在我回顾我的代码,其中存在耦合代码,其中客户端代码在将实体添加到集合后对其进行处理。跨度> 你对只读集合是正确的,我的代码不起作用。至于代码味道,我的意思是:***.com/questions/387937/… 我不确定我是否完全同意这个问题的主要答案,但我确实认为我需要避免暴露我的收藏。答案提到 ListIList<>
,您实际上使实现更容易使用List<>
以外的其他东西 - 例如Entity[]
数组。这个想法是使用接口来定义合约,而不是在这些合约中强制执行细节。指定一个具体的集合类型(如List
)是在没有真正需要的情况下强制执行一个实现细节。通过使用接口,您实际上可以更轻松地模拟事物。
至于您对AddEntity()
方法而不是公开集合的建议,这是一个很好的建议。参见得墨忒耳法则 (en.wikipedia.org/wiki/Law_of_Demeter)以上是关于Rhino Mocks:实例化 Mock 属性,以便 Expectation 可以引用它的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 Rhino Mocks Partial Mock 方法调用没有被模拟?