NHibernate Unit测试失败,出现Null Reference Exception

时间:2018-03-30 13:37:54

标签: c# nhibernate mocking

我的测试是使用像这样的模拟数据设置的

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" }
};

this.mockUnitOfWork.Setup(x => x.Query<Core.Domain.Person>()).Returns(persons.AsQueryable);

在测试人员的代码中,这样检索

private Dictionary<string, Domain.Person> GetPersons(IEnumerable<string> wurAccounts)
{
    var accounts = wurAccounts.ToList();
    return this.session.Query<Domain.Person>()
        .Where(x => accounts.Contains(x.WurAccount))
        .ToDictionary(x => x.WurAccount);
}

当我运行测试时,我在这里得到一个NullReferenceException:

at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
   at Remotion.Linq.QueryableBase`1.GetEnumerator()
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector)
   at Wur.P2G.Core.Services.PersonSynchronizer.GetPersons(IEnumerable`1 wurAccounts) in C:\Projects\P2G\P2G\Sources\Wur.P2G.Core\Services\PersonSynchronizer.cs:line 112

修改

我能够把它归结为仍然导致NullReference异常的这段代码:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NHibernate;
using NHibernate.Linq;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Wur.P2G.Core.Services.Tests
{
    public interface IUnitOfWork : IDisposable
    {
        ISession Session { get; }
        IQueryable<T> Query<T>();
        void BeginTransaction();
        void Commit();
        void Rollback();
    }

    public class Person
    {
        public virtual string WurAccount { get; set; }
        public virtual string DisplayName { get; set; }
        public virtual string Email { get; set; }
        public virtual bool HasValidEmail => true;
        public override string ToString() => WurAccount;
    }

    [TestClass()]
    public class PersonSynchronizerTests
    {
        private Mock<IUnitOfWork> mockUnitOfWork;
        private Mock<ISession> mockSession;

        [TestInitialize]
        public void Initialize()
        {
            this.mockUnitOfWork = new Mock<IUnitOfWork>();
            this.mockSession = new Mock<ISession>();
            this.mockUnitOfWork.Setup(x => x.Session).Returns(this.mockSession.Object);
        }

        [TestMethod()]
        public void GetPersonsTest()
        {
            var persons = new List<Person>
            {
                new Person { DisplayName = "Coordinator 1", Email="coordinator01@wur.nl", WurAccount = "coord001" },
                new Person { DisplayName = "Coordinator 2", Email="coordinator02@wur.nl", WurAccount = "coord002" }
            };

            this.mockUnitOfWork.Setup(x => x.Query<Person>()).Returns(persons.AsQueryable);

            var wurAccounts = new[] { "coord001", "coord002" };

            var accounts = wurAccounts.ToList();
            var personsRead = mockSession.Object.Query<Person>()
                .Where(x => accounts.Contains(x.WurAccount))
                .ToDictionary(x => x.WurAccount);
        }
    }
}

更多文字,因为愚蠢的编辑想要它。

1 个答案:

答案 0 :(得分:1)

虽然错误消息显示该问题与NHibernate.Linq有关,但到目前为止显示的所有代码都与NHibernate无关,除非您没有显示正在使用它的内容。

到目前为止显示的代码应该按预期工作,如下面基于提供的原始示例的最小,完整和可验证的示例所示。

[TestClass]
public class PersonSynchronizerTest {
    [TestMethod]
    public void PersonSynchronizer_GetPerson_Should_Return_Two() {
        //Arrange
        var wurAccounts = new[] { "coord001", "coord002" };
        var persons = new List<Person> {
            new Person { DisplayName = "Coordinator 1", Email="coordinator01@wur.nl", WurAccount = wurAccounts[0] },
            new Person { DisplayName = "Coordinator 2", Email="coordinator02@wur.nl", WurAccount = wurAccounts[1] }
        };

        var mockSession = new Mock<ISession>();
        mockSession.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable); //<-- setup session

        var mockUnitOfWork = new Mock<IUnitOfWork>();
        mockUnitOfWork.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable);
        mockUnitOfWork.Setup(_ => _.Session).Returns(mockSession.Object); //<-- UoW returns session

        var subject = new PersonSynchronizer(mockUnitOfWork.Object);

        //Act
        var actual = subject.GetPersons(wurAccounts);

        //Assert
        actual.Should()
            .NotBeNull()
            .And.HaveCount(wurAccounts.Length);
    }

    public class PersonSynchronizer {
        private IUnitOfWork unitOfWork;
        private ISession session;

        public PersonSynchronizer(IUnitOfWork uow) {
            this.unitOfWork = uow;
            this.session = unitOfWork.Session;
        }
        public Dictionary<string, Person> GetPersons(IEnumerable<string> wurAccounts) {
            var accounts = wurAccounts.ToList();
            return this.session.Query<Person>()
                .Where(x => accounts.Contains(x.WurAccount))
                .ToDictionary(x => x.WurAccount);
        }
    }

    public class Person {
        public string DisplayName { get; set; }
        public string Email { get; set; }
        public string WurAccount { get; set; }
    }

    public interface IUnitOfWork : IDisposable {
        ISession Session { get; }
        IQueryable<T> Query<T>();
        void BeginTransaction();
        void Commit();
        void Rollback();
    }

    public interface ISession {
        IQueryable<T> Query<T>();
    }
}

上面的代码段在测试时按预期传递。

我建议检查是否有任何可能与默认Linq Extensions冲突的NHibernate扩展方法,导致遇到问题。