尝试通过Mock枚举时出现NullReferenceException

时间:2013-11-25 17:10:36

标签: c# unit-testing kentico justmock

我得到一个奇怪的NullReferenceException,在尝试模拟集合进行枚举时我无法理解。我不认为这是由Mock引起的任何事情,但我并非100%肯定。任何人都可以发现我正在做的任何愚蠢行为吗?

InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
foreach (OrderItemInfo orderItem in orders)
{
    // Exception thrown on the first attempt to get an OrderItem in the foreach
}

此代码行的堆栈跟踪如下:

  

System.NullReferenceException:未将对象引用设置为实例
  一个对象。结果StackTrace:在   CMS.SettingsProvider.ObjectDataSet 1.GetEnumerator() at
CMS.SettingsProvider.ObjectDataSet
1.GetObjectEnumerator()在
  CMS.SettingsProvider.InfoDataSet`1.d__0.MoveNext()
  在......

集合的内容只是IEnumerable的包装器。在我的情况下,这应该让你知道发生了什么。 GetEnumerator(隐式和非隐式)实现只需调用值。

    private IEnumerable<T> values;

    /// <summary>
    /// Initializes a new instance of the <see cref="MockDataSet{T}"/> class.
    /// </summary>
    /// <param name="values">The values.</param>
    public MockDataSet(IEnumerable<T> values)
    {
        if (values == null)
            throw new ArgumentNullException("values");

        this.values = values;
    }

值中有一个值,我可以通过监视窗口枚举...

enter image description here

有谁能解释我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

这有点奇怪,我认为部分归结为下面的CMS(Kentico)。我之前遇到过一个问题,我在Unable to call ToArray() on 3rd party class上发了一个问题,我才意识到这可能会产生同样的影响。

似乎InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);的结果很难让编译器确定其类型。因此,我认为演员阵容正在下面说

((IEnumerable<OrderItemInfo>)orders)

我认为这是失败的,导致IEnumerable为null,因此NullReferenceException。决议是每个项目的简单演员:

InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
foreach (OrderItemInfo orderItem in orders.Cast<OrderItemInfo>())
{
   // Now works
}

答案 1 :(得分:0)

orders为空。你认为这不是因为循环已经开始但是记住它被评估为懒惰。

更改这样的代码,它不会失败:

InfoDataSet<OrderItemInfo> orders = OrderItemInfoProvider.GetOrderItems(orderInfo.OrderID);
if (orders != null)
{
  foreach (OrderItemInfo orderItem in orders)
  {
      // Exception thrown on the first attempt to get an OrderItem in the foreach
  }
}

请记住,每当您在调试器中查看某些内容时,周期时间已经过了很长时间 - 如果您有任何异步更新,它可能还没有完成。