1

我在单元测试中使用 NMock2 (2.1.3641.27570)。

IList<MyObj> values = _mock.NewMock<IList<MyObj>>();

当我的测试对象调用我的模拟对象上的Valuesget 属性时,我返回那个模拟:

Expect.AtLeastOnce.On(_myKeepMock).GetProperty("Values").Will(Return.Value(values));

然后我希望value将哪个 aMyObj添加到我的列表中values

Expect.AtLeastOnce.On(values).Method("Add").With(value);

为了避免unexpected invocation of list'1.Add在执行时,我知道我必须重写类Equals中的方法MyObj

public override bool Equals(object obj) { ...}

并按值而不是参考进行比较。但是在执行测试时它甚至不会被调用(断点未命中)。

当调用中添加到列表中的项与被测对象添加的项的值相等时,我需要做什么才能通过测试?

我阅读了有关自定义匹配器的信息,但不确定这些是否适用于此。

更新

完整示例:

using System.Collections.Generic;
using System.Linq;
using NMock2;
using NUnit.Framework;

public class Data
{
    public int Val { get; set; }

    public Data(int val) { Val = val; }


}
public class ModData
{
    public int Val { get; set; }


    protected bool Equals(ModData other)
    {
        return this.Val.Equals(other.Val);
    }

    public override int GetHashCode()
    {
        return this.Val.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        ModData m = (ModData)obj;

        return m != null && this.Val == m.Val;
    }

}


public interface IAllData
{
    IList<Data> Data { get; set; }
    IList<ModData> ModData { get; set; }
}

public class AllData : IAllData
{
    public IList<Data> Data { get; set; }
    public IList<ModData> ModData { get; set; }


}

public class Calco
{
    private IAllData _allData;

    public Calco(IAllData allData)
    {
        _allData = allData;
    }

    public void Sum()
    {
        _allData.ModData.Add(new ModData { Val = _allData.Data.Sum(d => d.Val) });
    }
}





public class CalcoTest
{
    [Test]
    public void Test()
    {
        Mockery mockery = new Mockery();
        IList<Data> data = new List<Data>();
        IList<ModData> modData = mockery.NewMock<IList<ModData>>();
        IAllData allData = mockery.NewMock<IAllData>();

        ModData modDatum = new ModData { Val = 4 };

        data.Add(new Data(1));
        data.Add(new Data(10));

        Calco c = new Calco(allData);



        Expect.AtLeastOnce.On(allData).GetProperty("Data").Will(Return.Value(data));
        Expect.AtLeastOnce.On(allData).GetProperty("ModData").Will(Return.Value(modData));
        Expect.AtLeastOnce.On(modData).Method("Add").With(modDatum);

        c.Sum();

        mockery.VerifyAllExpectationsHaveBeenMet();

    }
}

输出:

NMock2.Internal.ExpectationException : unexpected invocation of list`1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)
Expected:   
  at least 1 time: allData.Data, will return <System.Collections.Generic.List`1[WRM.Common.RiskCalculation.Tests.Data]> [called 1 time]
  at least 1 time: allData.ModData, will return <list`1> [called 1 time]
  at least 1 time: list`1.Add(equal to <WRM.Common.RiskCalculation.Tests.ModData>) [called 0 times]

注意它是如何期望调用的list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>) ,然后显示它没有调用list'1.Add(<WRM.Common.RiskCalculation.Tests.ModData>)

4

1 回答 1

1

自定义匹配器就是答案: http: //nmock.sourceforge.net/advanced.html

public class IsMod
{
    public static Matcher Equal(ModData otherMod)
    {
        return new ModMatcher(otherMod);
    }
}

internal class ModMatcher : Matcher
{
    private readonly ModData _mod;

    public ModMatcher(ModData mod)
    {
        _mod = mod;
    }

    public override bool Matches(object o)
    {

        ModData m = (ModData)o;
        return _mod.Val.Equals(m.Val);
    }

    public override void DescribeTo(TextWriter writer)
    {
        writer.Write("Value same ");
        writer.Write(_mod.Val);
    }
}

进而

Expect.AtLeastOnce.On(modData).Method("Add").With(IsMod.Equal(modDatum));

完毕!

于 2017-12-08T02:45:11.863 回答