我正在为MVC Web应用程序编写单元测试,并且我已经得到空引用异常,因为模拟测试对象只被部分初始化.我知道哪一行抛出异常,它看起来像这样:
return Supervisor.RegistrationInformation.Registrations .Any(r => r.RegistrationCountry.IsUSAOrCandada() && (!DatesWorked.Start.HasValue || r.RegistrationDate <= DatesWorked.Start.Value) && (!DatesWorked.End.HasValue || r.RegistrationExpirationDate >= DatesWorked.End.Value) && //...
在那里有很多参考,其中任何一个都可能是问题.但是,NullReferenceException本身似乎没有捕捉到哪个引用消失了.我传入一个lambda的事实是另一个挑战:据我所知,我不能在调试期间通过lambda,看看哪些成员是空的.
有什么办法可以执行以下一项或两项:
> Visual Studio告诉我哪个引用抛出NullReferenceException?
>没有,有没有办法使调试器通过lambda表达式(或只是悬停在事物上看到它们的值),因为它正在被Any评估?
我觉得必须有办法做这些事情,但我似乎找不到.我在VS2010 Premium,我有Resharper,VS电动工具和一些其他安装的其他扩展.如果有这样的附加功能,我会很好的.
编辑:
正如Eric Lippert指出的那样,当代码已经在Release配置中被编译时,无法确定NR异常的来源.我只是要求在调试模式下工作.如果Visual Studio(或VS的一些扩展)可以在调试时跟踪引用源,这将回答我的问题.
编辑2:
第二个问题 – 如何破解和通过一个lambda – 已被回答,但我仍然想知道是否有一种自动的方式来追踪一个空的引用.
解决方法
没有一般的方式做你想要的,不.要了解为什么,请考虑抛出空引用异常时发生的情况.假设您是编译器,并且必须发出代码来处理对abc.Def.Ghi.Jkl()的调用,其中abc是本地的,Def和Ghi是引用类型的字段,Jkl是一种方法.没有IL指令可以做一些复杂的事情;你必须打破它.所以你发出一个等效程序的代码,其中的一切都简单得多.你发出程序片段:
temp1 = abc.Def; temp2 = temp1.Ghi; temp2.Jkl();
假设temp2为null,因为Ghi为null.在调用Jkl之前,这个事实将不会被发现,在这一点上抛出异常的事情并不知道如何初始化temp2.那很久以前,过去的纳秒和机器代码没有过去的记忆;空引用并没有保留一点注意,它表明null来自哪里,除了当你说“a = bc”之外,结果的数字十二不保持一个注释,说“我是总和的b和c“.