模拟将项目添加到 .NET NMock2 中的列表
Mocking adding items to a list in .NET NMock2
我在单元测试中使用 NMock2 (2.1.3641.27570)。
IList<MyObj> values = _mock.NewMock<IList<MyObj>>();
当我的测试对象在我的模拟对象上调用 Values
get 属性 时模拟我 return:
Expect.AtLeastOnce.On(_myKeepMock).GetProperty("Values").Will(Return.Value(values));
然后我希望 value
这是一个 MyObj
被添加到我的列表 values
:
Expect.AtLeastOnce.On(values).Method("Add").With(value);
为了避免执行时 unexpected invocation of list'1.Add
我知道我必须重写 MyObj
class:
中的 Equals
方法
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>)
自定义匹配器就是答案: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));
完成!
我在单元测试中使用 NMock2 (2.1.3641.27570)。
IList<MyObj> values = _mock.NewMock<IList<MyObj>>();
当我的测试对象在我的模拟对象上调用 Values
get 属性 时模拟我 return:
Expect.AtLeastOnce.On(_myKeepMock).GetProperty("Values").Will(Return.Value(values));
然后我希望 value
这是一个 MyObj
被添加到我的列表 values
:
Expect.AtLeastOnce.On(values).Method("Add").With(value);
为了避免执行时 unexpected invocation of list'1.Add
我知道我必须重写 MyObj
class:
Equals
方法
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>)
自定义匹配器就是答案: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));
完成!