1

I have a class SendNotificationsToSubscribersCommandHandler with the following Method Handle and I have test method GetAllSubscriptionsWithCorrectParamsProductId() to check that Handle method returns correct List.

I get following error:

Message: 
    Test method Grand.Services.Tests.Commands.Handlers.Catalog.SendNotificationsToSubscribersCommandHandlerTest.GetAllSubscriptionsWithCorrectParamsProductId threw exception: 
    System.InvalidCastException: Unable to cast object of type 'System.Linq.EnumerableQuery`1[Grand.Domain.Catalog.BackInStockSubscription]' to type 'MongoDB.Driver.Linq.IMongoQueryable`1[Grand.Domain.Catalog.BackInStockSubscription]'.
  Stack Trace: 
    MongoQueryable.Where[TSource](IMongoQueryable`1 source, Expression`1 predicate)

SendNotificationsToSubscribersCommandHandler

public class SendNotificationsToSubscribersCommandHandler : IRequestHandler<SendNotificationsToSubscribersCommand, IList<BackInStockSubscription>>
    {
        private readonly ICustomerService _customerService;
        private readonly IWorkflowMessageService _workflowMessageService;
        private readonly IRepository<BackInStockSubscription> _backInStockSubscriptionRepository;

        public SendNotificationsToSubscribersCommandHandler(
            ICustomerService customerService,
            IWorkflowMessageService workflowMessageService,
            IRepository<BackInStockSubscription> backInStockSubscriptionRepository)
        {
            _customerService = customerService;
            _workflowMessageService = workflowMessageService;
            _backInStockSubscriptionRepository = backInStockSubscriptionRepository;
        }

        public async Task<IList<BackInStockSubscription>> Handle(SendNotificationsToSubscribersCommand request, CancellationToken cancellationToken)
        {
            if (request.Product == null)
                throw new ArgumentNullException("product");

            int result = 0;

            var query = _backInStockSubscriptionRepository.Table;
            //product
            query = query.Where(biss => biss.ProductId == request.Product.Id);

            //warehouse
            if (!string.IsNullOrEmpty(request.Warehouse))
                query = query.Where(biss => biss.WarehouseId == request.Warehouse);

            //warehouse
            if (!string.IsNullOrEmpty(request.AttributeXml))
                query = query.Where(biss => biss.AttributeXml ==  request.AttributeXml);

            query = query.OrderByDescending(biss => biss.CreatedOnUtc);
            var subscriptions = await query.ToListAsync();
            //var subscriptions = await GetAllSubscriptionsByProductId(request.Product.Id, request.AttributeXml, request.Warehouse);
            foreach (var subscription in subscriptions)
            {
                var customer = await _customerService.GetCustomerById(subscription.CustomerId);
                //ensure that customer is registered (simple and fast way)
                if (customer != null && CommonHelper.IsValidEmail(customer.Email))
                {
                    var customerLanguageId = customer.GetAttributeFromEntity<string>(SystemCustomerAttributeNames.LanguageId, subscription.StoreId);
                    await _workflowMessageService.SendBackInStockNotification(customer, request.Product, subscription, customerLanguageId);
                    result++;
                }
            }

            return subscriptions;

        }
}

My test method:

    [TestClass()]
        public class SendNotificationsToSubscribersCommandHandlerTest
        {
            private Mock<ICustomerService> _mockCustomerService;
            private Mock<IRepository<BackInStockSubscription>> _mockBackInStockSubscriptionRepository;
            private Mock<IMongoQueryable<BackInStockSubscription>> _mongoQueryableMock;
            private IQueryable<BackInStockSubscription> _expectedQueryable;
            private List<BackInStockSubscription> _expected;
            private Mock<IWorkflowMessageService> _mockWorkflowMessageService;
            private SendNotificationsToSubscribersCommandHandler _handler;
            private SendNotificationsToSubscribersCommand _sendNotificationsToSubscribersCommand;
    
            [TestInitialize()]
            public void Init()
            {
                _expected = new List<BackInStockSubscription>
                {
                    new BackInStockSubscription { WarehouseId = "11", ProductId = "11" },
                    new BackInStockSubscription { WarehouseId = "11", ProductId = "11" }
                };
                _mockCustomerService = new Mock<ICustomerService>();
                _mockBackInStockSubscriptionRepository = new Mock<IRepository<BackInStockSubscription>>();
                _expectedQueryable = _expected.AsQueryable();
    
                _mongoQueryableMock = new Mock<IMongoQueryable<BackInStockSubscription>>();
 _mongoQueryableMock.As<IEnumerable<BackInStockSubscription>>();
                _mongoQueryableMock.Setup(x => x.ElementType).Returns(_expectedQueryable.ElementType);
                _mongoQueryableMock.Setup(x => x.Expression).Returns(_expectedQueryable.Expression);
                _mongoQueryableMock.Setup(x => x.Provider).Returns(_expectedQueryable.Provider);
                _mongoQueryableMock.Setup(x => x.GetEnumerator()).Returns(_expectedQueryable.GetEnumerator());
                _mockBackInStockSubscriptionRepository.Setup(x => x.Table).Returns(_mongoQueryableMock.Object);
    
                _mockWorkflowMessageService = new Mock<IWorkflowMessageService>();
                _sendNotificationsToSubscribersCommand = new SendNotificationsToSubscribersCommand { Product = new Product { Id = "11"}, Warehouse = "11" };
    
                _handler = new SendNotificationsToSubscribersCommandHandler(_mockCustomerService.Object, _mockWorkflowMessageService.Object, _mockBackInStockSubscriptionRepository.Object);
            }
    
            [TestMethod()]
            public async Task GetAllSubscriptionsWithCorrectParamsProductId()
            {
                var result = await _handler.Handle(_sendNotificationsToSubscribersCommand, default);
                var resultList = result.ToList();
                Assert.AreEqual(resultList, _expected);
            }
        }

I get error on line

query = query.Where(biss => biss.ProductId == productId);

UPDATE

When I debug application, property _backInStockSubscriptionRepository.Table has Expression.Value = {aggregate([])} If I debug test method property Table of Mock object has Expression.Value with Value = System.Collections.Generic.List<Grand.Domain.Catalog.BackInStockSubscription> with my two objects.

Any help is greatly appreciated

Stefan Hansch
  • 1,550
  • 4
  • 22
  • 55

1 Answers1

0

Take a look at here: How to mock a class that implements multiple interfaces

Try something like this:

_mongoQueryableMock = new Mock<IMongoQueryable<BackInStockSubscription>>();
_mongoQueryableMock.As<IEnumerable<BackInStockSubscription>>();
...
Michael
  • 3,350
  • 2
  • 21
  • 35