[英]Using Moq to verify a method call on class in a collection
I'm not sure if I'm using Moq the right way, so if anyone could help, I'd be grateful. 我不确定我是否以正确的方式使用Moq,所以如果有人可以提供帮助,我将不胜感激。
I want to test the call of Clone() method on object in a collection. 我想测试集合中对象的Clone()方法调用。 The test looks like this:
测试如下所示:
[Test]
public void CloneTest()
{
var mdFake = new Mock<MachineDecision>();
var clonable = mdFake.As<ICloneable>();
clonable.Setup(x => x.Clone()).Verifiable();
var decision = new Decision()
{
MachineDecisions = new List<MachineDecision> { mdFake.Object }
};
var newDecision = (Decision) decision.Clone();
clonable.Verify(x => x.Clone());
}
The test fails: Moq.MockException : Expected invocation on the mock at least once, but was never performed: x => x.Clone()
but I believe it should actually pass. 测试失败:
Moq.MockException : Expected invocation on the mock at least once, but was never performed: x => x.Clone()
但我认为它实际上应该通过。
Used classes look as follows: 使用的类如下所示:
public class Decision : Entity<Guid>, ICloneable
{
public Decision()
{
Id = Guid.NewGuid();
MachineDecisions = new List<MachineDecision>();
}
public List<MachineDecision> MachineDecisions { get; set; }
public object Clone()
{
var obj = new Decision();
if (this.MachineDecisions != null)
{
obj.MachineDecisions = MachineDecisions.Select(item => (MachineDecision) item.Clone()).ToList();
}
return obj;
}
}
public class MachineDecision : Entity<Guid>, ICloneable
{
//...
}
There are two options available. 有两个选项。
First , you can make an implementation of method Clone()
virtual and your test will be 'Green' 首先 ,您可以虚拟实现方法
Clone()
的实现,并且测试将为“绿色”
public class MachineDecision : Entity<Guid>, ICloneable
{
public virtual object Clone()
{
throw new NotImplementedException();
}
}
Second , you can invoke Clone()
method from ICloneable
interface: (MachineDecision)(item as ICloneable).Clone()
; 其次 ,您可以从
ICloneable
接口调用Clone()
方法: (MachineDecision)(item as ICloneable).Clone()
; and your test will be 'Green' also. 并且您的测试也将为“绿色”。
public class Decision : Entity<Guid>, ICloneable
{
public Decision()
{
Id = Guid.NewGuid();
MachineDecisions = new List<MachineDecision>();
}
public List<MachineDecision> MachineDecisions { get; set; }
public object Clone()
{
var obj = new Decision();
if (this.MachineDecisions != null)
{
obj.MachineDecisions = MachineDecisions.Select(item =>
{
return (MachineDecision)(item as ICloneable).Clone();
}).ToList();
}
return obj;
}
}
I realise that now it is not the best code but it is up to you how to refactor it further. 我意识到现在这不是最好的代码,但是由您自己决定如何进一步重构它。
I'd do it like this: 我会这样:
[Test]
public void CloneTest()
{
// create the mock
var mdFake = new Mock<MachineDecision>();
var decision = new Decision
{
// setup (pass it to my collection)
MachineDecisions = new List<MachineDecision> { mdFake.Object }
};
// call the method being tested (you need to make Clone() virtual)
decision.Clone();
// check for the side effects -> It was called once !
mdFake.Verify(x => x.Clone(), Times.Once());
}
I hope this helps you. 我希望这可以帮助你。
EDIT - I'm sorry, as it was pointed in the comments - I forgot to mention, that what I'm suggesting requires you to make Clone()
(in MachineDecision
) - virtual
, which might not be ideal in your case. 编辑 -很抱歉,正如评论中所指出的-我忘了提及,我的建议是要求您将
Clone()
(在MachineDecision
)- virtual
,这在您的情况下可能并不理想。
Try this: 尝试这个:
...
clonable.Expect(x => x.Clone()).Verifiable().Returns(null);
...
clonable.Verify();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.