你如何使用NSubstitute模拟IEnumerable <t> ElementAt()?

时间:2016-02-04 18:36:43

标签: linq unit-testing mocking nsubstitute

我一直在实现正确的技术来模拟IEnumerable的Linq方法。

{
    var qs = Substitute.For<IEnumerable<object>>();
    qs.ElementAt(i).Returns(q);
    qs.Count().Returns(i);
}

这是为了测试一种方法,该方法包含随机或以受控方式从列表中提取项目。

private IEnumerable<T> list;
async object Save(object obj, byte i = 0)
{
     var random = new Random();
     var index = i == 0 ? random.Next(0, list.Count()) : i;
     return list.ElementAt(index);
}

这样做会导致:

at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at System.Linq.Enumerable.ElementAt[TSource](IEnumerable`1 source, Int32 index)
   at King.Azure.Unit.Test.Data.StorageQueueShardsTests.<Save>d__11.MoveNext() in C:\Users\jefkin\Documents\GitHub\King.Azure\King.Azure.Unit.Test\Data\StorageQueueShardsTests.cs:line 127
--- End of stack trace from previous location where exception was thrown ---
   at NUnit.Framework.Internal.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunAsyncTestMethod(TestExecutionContext context)
Result Message: 
System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

1 个答案:

答案 0 :(得分:3)

可以模拟的唯一方法是接口方法或类中的虚方法。

由于ElementAt是一种扩展方法,而不是IEnumerable<T>方法,因此无法对其进行模拟。

测试此方法的最佳方法是使用List<T>代替并相应地设置列表而不使用NSubstitute。

例如:

var qs = new List<object> {
    obj1,
    obj2,
    obj3
};

var result = sut.Save(obj, i);

var expected = qs[i];
Assert.Equal(expected, result);