NHibernate单元测试触发空引用异常,附模拟代码求排查
排查和解决NHibernate单元测试中的空引用异常
空引用异常通常是因为访问了未初始化的对象或其成员,结合你的测试场景,我们一步步拆解问题并给出解决方案:
1. 先检查待测试类中Dictionary的初始化状态
这是最常见的触发原因——你的私有Dictionary可能只做了声明,却没有实例化。比如你的待测试类代码可能是这样:
private Dictionary<string, Core.Domain.Person> _personDictionary; // 仅声明,未初始化 public void LoadPersonData() { var persons = _unitOfWork.Query<Core.Domain.Person>(); // 直接操作_personDictionary,此时它还是null foreach(var person in persons) { _personDictionary.Add(person.WurAccount, person); } }
解决方法很简单,在类的构造函数或者字段声明时初始化Dictionary:
// 方式1:字段声明时直接初始化 private Dictionary<string, Core.Domain.Person> _personDictionary = new Dictionary<string, Core.Domain.Person>(); // 方式2:在构造函数中初始化 public YourServiceClass(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; _personDictionary = new Dictionary<string, Core.Domain.Person>(); }
2. 确认Mock的UnitOfWork是否正确注入
如果待测试类没有拿到你模拟的mockUnitOfWork,实际使用的_unitOfWork会是null,调用Query<Person>()时必然抛出空引用。
确保测试代码中是这样创建待测试实例的:
// 初始化Mock var mockUnitOfWork = new Mock<IUnitOfWork>(); // 设置Query方法的返回值 var persons = new List<Core.Domain.Person> { new Core.Domain.Person { DisplayName = "Coordinator 1", Email="coordinator01@wur.nl", WurAccount = "coord001" }, new Core.Domain.Person { DisplayName = "Coordinator 2", Email="coordinator02@wur.nl", WurAccount = "coord002" } }; mockUnitOfWork.Setup(x => x.Query<Core.Domain.Person>()).Returns(persons.AsQueryable()); // 关键:将Mock的实例注入到待测试类中 var yourTestService = new YourTestService(mockUnitOfWork.Object);
如果你的待测试类是通过静态工厂、未正确配置的依赖容器获取UnitOfWork,Mock就不会生效,导致实际使用的是null对象。
3. 验证Mock的Setup是否匹配实际调用
有时候Mock的Setup和待测试代码的调用不匹配,会导致Mock返回null。比如:
- 你Setup的是无参的
Query<Person>(),但实际代码调用的是带参数的重载 - 泛型参数的命名空间写法不一致(比如代码里用
using Core.Domain;简化了类型,而Setup里写了全限定名,虽然本质是同一个类型,但Moq的匹配可能出问题)
你可以在测试末尾添加验证,确认Mock的方法确实被调用了:
// 执行待测试方法 yourTestService.YourTestMethodToTest(); // 验证Query方法是否被调用过一次 mockUnitOfWork.Verify(x => x.Query<Core.Domain.Person>(), Times.Once);
如果验证失败,说明Setup的写法需要调整以匹配实际调用。
4. 检查Dictionary填充逻辑中的属性访问
虽然你的测试数据给Person的几个属性赋了值,但如果填充Dictionary时用到了未初始化的Person属性,也会触发空引用。比如:
// 假设代码里用了某个未设置的属性作为字典Key _personDictionary.Add(person.SomeUninitializedProperty, person);
这种情况需要确保测试数据中,Dictionary依赖的所有Person属性都被正确赋值,或者在代码中添加null检查。
5. 调试定位具体空引用位置
如果以上排查都没解决问题,直接在测试中加断点,执行到抛出异常的位置,查看:
- 是
_unitOfWork为null? - 是
_personDictionary为null? - 是
Query<Person>()返回了null? - 还是某个Person对象的属性为null?
调试能快速定位到问题根源,再针对性解决即可。
内容的提问来源于stack exchange,提问作者Paul Sinnema
相关产品推荐
相关产品推荐

