Unit-тестирование NHibernate с помощью Moq: правильный Mock для работы .ToListAsync()

Необходимо создать юнит тесты с помощью Moq в приложении на ASP.NET Core MVC, как ORM используется NHibernate. Столкнулся с проблемой, что асинхронные операции NHibernate(в частности ToListAsync) требуют специфической заглушки. В процессе поиска решения был написан вот такой, почти работающий, вариант

var entities = new List<RequestRole>
        {
            new RequestRole()
            {
                Id = 0,
                RequestOperator = new RequestOperator() { Id = 1 }
            },
            new RequestRole()
            {
                Id = 1,
                RequestOperator = new RequestOperator() { Id = 2 }
            }
        }
        .AsQueryable();

        // для работы ToListAsync нужно сделать именно INhQueryProvider
        var queryableProviderMock = new Mock<INhQueryProvider>();
        queryableProviderMock.Setup(x => x.ExecuteAsync<IEnumerable<RequestRole>>(It.IsAny<Expression>(), It.IsAny<CancellationToken>()))
                             .ReturnsAsync(entities);

        // свой IQueryable для установки INhQueryProvider
        var queryableMock = new Mock<IQueryable<RequestRole>>();
        queryableMock.Setup(x => x.Provider).Returns(queryableProviderMock.Object);
        queryableMock.Setup(x => x.Expression).Returns(entities.Expression);
        queryableMock.Setup(x => x.GetEnumerator()).Returns(entities.GetEnumerator());
        queryableMock.Setup(x => x.ElementType).Returns(entities.ElementType);

        // для того, чтобы where не падал с ошибкой приведения типов, эмулируем CreateQuery 
        // данная реализация также просто выключает его работу
        queryableProviderMock.As<INhQueryProvider>()
                             .Setup(x => x.CreateQuery<RequestRole>(It.IsAny<Expression>()))
                             .Returns(queryableMock.Object);

        var session = new Mock<ISession>();
        session.Setup(s => s.Query<RequestRole>()).Returns(queryableMock.Object);

        var returns = session.Object.Query<RequestRole>();

        // проверка работоспособности 
        // в результате возвращаются обе записи
        var tolistasync = await returns
            .Where(x => x.Id != 0)
            .ToListAsync();

        // установка заглушки в вызываемый метод
        idataStore.Setup(x => x.GetAll<RequestRole>()).Returns(returns);

В результате запрос к базе эмулируется, но не работают условия where, так как CreateQuery является просто заглушкой, возвращающей запрос без условий.

Подскажите, есть ли способ сделать полностью рабочий вариант тестирования методов, использующих асинхронные операции NHibernate?

UPD: Решение найдено в английской версии stackoverflow https://stackoverflow.com/a/61420204/13398437


Ответы (0 шт):