public void PlaceOrder_AllProductsInStock_DoesNotThrowException()
        {
            // Arrange
            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(new Customer());
            _orderFulfillmentService.Stub(or => _orderFulfillmentService.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _taxRateService.Stub(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything)).Return(new List<TaxEntry> { new TaxEntry() });

            _productRepository.Expect(pr => pr.IsInStock("apple")).Return(true);
            _productRepository.Expect(pr => pr.IsInStock("apple2")).Return(true);

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } }
                }
            };

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            _productRepository.VerifyAllExpectations();
        }
        public void BeforeEach()
        {
            _productRepo = Substitute.For<IProductRepository>();
            _orderFulfillmentService = Substitute.For<IOrderFulfillmentService>();
            _customerRepository = Substitute.For<ICustomerRepository>();
            _taxRateService = Substitute.For<ITaxRateService>();
            _emailService = Substitute.For<IEmailService>();

            _subject = new OrderService(_orderFulfillmentService,
                _customerRepository,
                _taxRateService,
                _emailService);

            _bestCustomer = new Customer
            {
                CustomerId = 42,
                PostalCode = "12345",
                Country = "Merica"
            };

            _listOfTaxEntries = new List<TaxEntry>
            {
                new TaxEntry {Description = "High Tax", Rate = (decimal) 0.60},
                new TaxEntry {Description = "Low Tax", Rate = (decimal) 0.10}
            };

            _orderConfirmation = new OrderConfirmation
            {
                OrderId = 1234,
                OrderNumber = "hello"
            };
            _customerRepository.Get(_bestCustomer.CustomerId.Value).Returns(_bestCustomer);
            _taxRateService.GetTaxEntries(_bestCustomer.PostalCode, _bestCustomer.Country).Returns(_listOfTaxEntries);
        }
        public void PlaceOrder_AllProductsNotInStock_DoesThrowException()
        {
            // Arrange
            _productRepository.Expect(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(false);

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } }
                }
            };

            // Act // Assert
            var exception = Assert.Throws<Exception>(() => orderService.PlaceOrder(order));
            Assert.That(exception.Message, Is.StringContaining("Not all products are in stock."));
        }
        public void PlaceOrder_CustomerIsInCustomerRepository_DoesNotThrowException()
        {
            // Arrange
            var expectedCustomerId = 1;

            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _orderFulfillmentService.Stub(or => or.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _taxRateService.Stub(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything)).Return(new List<TaxEntry> { new TaxEntry() });

            _customerRepository.Expect(c => c.Get(expectedCustomerId)).Return(new Customer {CustomerId = expectedCustomerId});

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple", Price = (decimal) 2.00},
                        Quantity = 2
                    },
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple2", Price = (decimal) 2.50 },
                        Quantity = 1
                    }
                }
            };

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            _customerRepository.VerifyAllExpectations();
        }
        public void PlaceOrder__NotUniqueByProductSKU__DoesThrowException()
        {
            // Arrange
            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product {Sku = "apple"} },
                    new OrderItem { Product = new Product {Sku = "apple"} },
                }
            };

            // Act // Assert
            var exception = Assert.Throws<Exception>(() => orderService.PlaceOrder(order));
            Assert.That(exception.Message, Is.StringContaining("The orderItems are not unique by Sku."));
        }
        public void PlaceOrder_TaxesNotInTaxRateService_TaxesIsEmpty()
        {
            // Arrange
            var customerId = 1;

            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _orderFulfillmentService.Stub(or => or.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _customerRepository.Stub(c => c.Get(customerId)).Return(new Customer {CustomerId = customerId});

            _taxRateService.Expect(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything))
                .Return(new List<TaxEntry>());

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = customerId,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple", Price = (decimal) 2.00},
                        Quantity = 2
                    },
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple2", Price = (decimal) 2.50 },
                        Quantity = 1
                    }
                }
            };

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            Assert.That(result.Taxes, Is.Empty);
        }
        public void PlaceOrder_OrderIsValid_ReturnOrderSummary()
        {
            // Arrange
            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(new Customer());
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _orderFulfillmentService.Stub(or => _orderFulfillmentService.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _taxRateService.Stub(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything)).Return(new List<TaxEntry> { new TaxEntry() });

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } }
                }
            };

            // Act // Assert
            var actual = orderService.PlaceOrder(order);
            Assert.IsInstanceOf<OrderSummary>(actual);
        }
        public void PlaceOrder_OrderIsValid_OrderSummaryContainsOrderTotal()
        {
            // Arrange
            var customer = new Customer { CustomerId = 1 };
            var taxRate1 = 1.5;
            var taxRate2 = 2.5;
            var netTotal = 6.50;

            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(customer);
            _orderFulfillmentService.Stub(or => or.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _taxRateService.Stub(t => t.GetTaxEntries(customer.PostalCode, customer.Country))
                .Return(new List<TaxEntry>
                {
                    new TaxEntry {Rate = (decimal) taxRate1},
                    new TaxEntry {Rate = (decimal) taxRate2},
                });

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple", Price = (decimal) 2.00},
                        Quantity = 2
                    },
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple2", Price = (decimal) 2.50 },
                        Quantity = 1
                    }
                }
            };
            var expectedOrderTotal = netTotal * taxRate1 + netTotal * taxRate2;

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            Assert.AreEqual(expectedOrderTotal, result.Total);
        }
        public void PlaceOrder_OrderIsValid_OrderSummaryContainsOrderId()
        {
            // Arrange
            var expectedOrderId = 1;
            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(new Customer());
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _taxRateService.Stub(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything)).Return(new List<TaxEntry> { new TaxEntry() });

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } },
                }
            };

            _orderFulfillmentService.Stub(or => or.Fulfill(order)).Return(new OrderConfirmation{OrderNumber = "1", OrderId = 1, });

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            Assert.That(result.OrderId, Is.EqualTo(expectedOrderId), "OrderId");
        }
        public void PlaceOrder_OrderIsValid_OrderSummaryContainsNetTotal()
        {
            // Arrange
            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(new Customer());
            _orderFulfillmentService.Stub(or => or.Fulfill(Arg<Order>.Is.Anything)).Return(new OrderConfirmation());
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _taxRateService.Stub(t => t.GetTaxEntries(Arg<String>.Is.Anything, Arg<String>.Is.Anything)).Return(new List<TaxEntry> { new TaxEntry() });

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple", Price = (decimal) 2.00},
                        Quantity = 2
                    },
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple2", Price = (decimal) 2.50 },
                        Quantity = 1
                    }
                }
            };

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            Assert.AreEqual(6.50, result.NetTotal);
        }
        public void PlaceOrder_OrderIsValid_OrderSummaryContainsApplicableTaxes()
        {
            // Arrange
            var expectedCustomerId = 1;
            var customer = new Customer{ CustomerId = expectedCustomerId};

            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(customer);
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);
            _orderFulfillmentService.Stub(or => _orderFulfillmentService.Fulfill(Arg<Order>.Is.Anything))
                .Return(new OrderConfirmation());
            _taxRateService.Stub(t => t.GetTaxEntries(customer.PostalCode, customer.Country))
                .Return(new List<TaxEntry> {new TaxEntry {Description = "USA"} });

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = expectedCustomerId,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } }
                }
            };

            // Act
            var result = orderService.PlaceOrder(order);

            // Assert
            Assert.That(result.Taxes.ToList().Exists(tax => tax.Description == "USA"));
        }
        public void PlaceOrder_OrderIsNotValid_ThrowsExceptionWithListOfWhyNotValid()
        {
            // Arrange
            _productRepository.Expect(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(false);

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                OrderItems = new List<OrderItem>
                {
                    new OrderItem { Product = new Product { Sku = "apple" } },
                    new OrderItem { Product = new Product { Sku = "apple2" } }
                }
            };

            // Act // Assert
            Assert.Throws<Exception>(() => orderService.PlaceOrder(order));
        }
        public void PlaceOrder_CustomerNotInCustomerRepository_DoesThrowException()
        {
            // Arrange
            _customerRepository.Stub(c => c.Get(Arg<int>.Is.Anything)).Return(null);
            _productRepository.Stub(pr => pr.IsInStock(Arg<string>.Is.Anything)).Return(true);

            var orderService = new OrderService(_productRepository, _orderFulfillmentService, _emailService, _customerRepository, _taxRateService);

            var order = new Order
            {
                CustomerId = 1,
                OrderItems = new List<OrderItem>
                {
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple", Price = (decimal) 2.00},
                        Quantity = 2
                    },
                    new OrderItem
                    {
                        Product = new Product { Sku = "apple2", Price = (decimal) 2.50 },
                        Quantity = 1
                    }
                }
            };
            // Act  // Assert
            var exception = Assert.Throws<Exception>(() => orderService.PlaceOrder(order));
            Assert.That(exception.Message, Is.StringContaining("The customer is null or cannot be retrieved."));
        }