簡體   English   中英

使用Moq驗證集合中類的方法調用

[英]Using Moq to verify a method call on class in a collection

我不確定我是否以正確的方式使用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
{
    //...
}

有兩個選項。

首先 ,您可以虛擬實現方法Clone()的實現,並且測試將為“綠色”

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

其次 ,您可以從ICloneable接口調用Clone()方法: (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;
        }
    }

我意識到現在這不是最好的代碼,但是由您自己決定如何進一步重構它。

我會這樣:

[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() (在MachineDecision )- virtual ,這在您的情況下可能並不理想。

嘗試這個:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM