我有一个需要模拟的对象列表:
var myMock = new Mock<IList<IValidatableTable>>();
我的意图是创建一个实现IValidatableTable
的对象的真实实例,如下所示:
var validatableTable = new ValidatableTable();
//... code that modifies the object the way I need it...
并设置我的mock,使其将此对象作为列表项之一返回。
我试过使用SetupGet、Setup,但我不知道该在lambda表达式中放入什么。我也试过用谷歌搜索,但只有一个线程接近我想要的c#如何模拟对象列表,即使这样也无济于事,因为我的编译器无法解析Catalogue。
你能帮我吗?
只要你不想检查列表的成员(例如Add
、Remove
(是否以特定的方式被调用,我就不会为列表创建mock,而是创建一个真实的列表。由于List<T>
是框架中一个基本且非常常用的成员,因此可以直接在测试中使用,而不必嘲笑它
IList<IValidatableTable> tables = new List<IValidatableTable>();
然后,您可以根据测试的需要,用模拟或真实对象来填充这个列表;如果要检查代码是否使用列表并调用IValidatableTable
上的方法,可以使用mocks:
var mockTbl = new Mock<IValidatableTable>();
// Add setups as needed
如果你在写的时候想添加一个真正的ValidatableTable
,你可以创建它并将其添加到你的列表中:
tables.Add(new ValidatableTable());
关于模拟列表
由于模拟列表是一个乏味的过程,如果你查看成员的数量及其特征(例如枚举器支持等(,你也可以在运行测试后检查列表中的项目是否按照你期望的方式进行了更改,例如:
- 长度符合您的期望吗
- 是否添加了具有预期数据的新项目
- 是否删除了本应删除的项目
从测试的角度来看:使用Add
添加项目对您来说重要吗?或者,如果稍后将代码更改为使用AddRange
来更有效地添加项目,可以吗?
在测试中的代码运行后检查列表时,您会发现相关的更改(只有当结果与您的预期不符时,测试才会失败(。相比之下,如果你嘲笑这个列表,你就会"微测试">方式,列表是如何在代码中使用的。当以意外的方式调用列表方法时,它将失败。IMO这将导致不相关的测试失败。因此,在大多数情况下,我宁愿不嘲笑这个列表。
Mock
的构造函数重载之一接受一个参数数组,以传递给模拟类型的构造函数,因此如果可以使用List<ValidatableTable>
而不是IList<ValidatableTable>
,则可以执行以下操作:
var constructorArgs = new List<ValidatableTable>
{
//Your "real instance"
new ValidatableTable(),
};
var myMock = new Mock<List<ValidatableTable>>(constructorArgs);
但在这一点上,我会质疑嘲笑List
的有用性,因为没有";行为;你真的可以改变——你所能做的就是控制内容,这感觉不需要Mock
。