使用Moq验证集合中类的方法调用

时间:2013-12-23 14:19:10

标签: c# nunit moq

我不确定我是否以正确的方式使用Moq,所以如果有人能提供帮助,我将不胜感激。

我想测试集合中对象的Clone()方法调用。测试看起来像这样:

[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()); 
}

测试失败:Moq.MockException : Expected invocation on the mock at least once, but was never performed: x => x.Clone()但我相信它应该实际通过。

使用的类看起来如下:

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
{
    //...
}

3 个答案:

答案 0 :(得分:3)

有两种选择。

首先,您可以对方法Clone()进行虚拟实施,您的测试将是&#39;绿色&#39;

public class MachineDecision : Entity<Guid>, ICloneable
{
    public virtual object Clone()
    {
        throw new NotImplementedException();
    }
}

第二次,您可以从Clone()界面调用ICloneable方法:(MachineDecision)(item as ICloneable).Clone();而你的考试将是“绿色”。还

    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;
        }
    }

我意识到现在它不是最好的代码,但是由你决定如何进一步重构它。

答案 1 :(得分:1)

我会这样做:

[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());
}

我希望这会对你有所帮助。

编辑 - 对不起,正如评论中指出的那样 - 我忘了提及,我所建议的要求你制作Clone()({{1} }}) - MachineDecision,在你的情况下可能并不理想。

答案 2 :(得分:0)

试试这个:

...
clonable.Expect(x => x.Clone()).Verifiable().Returns(null);
...
clonable.Verify();