using Moq; using NUnit.Framework; using System; using System.Collections.Generic; using System.Linq; using CandyHouseBase.DataModels; using CandyHouseBase.Exceptions; using CandyHouseBase.Extensions; using CandyHouseBase.Implementations; using CandyHouseBase.Interfaces.BusinessLogicsContracts; using CandyHouseBase.Interfaces.StoragesContracts; using Microsoft.Extensions.Logging; namespace CandyHouseTests.BusinessLogicsContractsTests { [TestFixture] internal class ProductBusinessLogicContractTests { private ProductBusinessLogicContract _productBusinessLogicContract; private Mock _productStorageContact; private Mock _ingredientStorageContact; [OneTimeSetUp] public void OneTimeSetUp() { _productStorageContact = new Mock(); _ingredientStorageContact = new Mock(); _productBusinessLogicContract = new ProductBusinessLogicContract( _productStorageContact.Object, _ingredientStorageContact.Object, new Mock().Object ); } [SetUp] public void SetUp() { _productStorageContact.Reset(); _ingredientStorageContact.Reset(); } [Test] public void GetAllProducts_ReturnsListOfRecords_Test() { // Arrange var ingredientId = Guid.NewGuid().ToString(); var product1 = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product1.Name = "Updated Cake"; product1.Description = "Updated delicious cake"; var product2 = new ProductDataModel( Guid.NewGuid().ToString(), "Pastry", "Sweet pastry", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Flour", "kg", 200) } ); product2.Name = "Updated Pastry"; product2.Description = "Updated sweet pastry"; var products = new List { product1, product2 }; _productStorageContact.Setup(x => x.GetList()).Returns(products); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product1.IngredientsItems[0]); // Act var list = _productBusinessLogicContract.GetAllProducts(); // Assert Assert.That(list, Is.Not.Null); Assert.That(list, Is.EquivalentTo(products)); Assert.That( list.All(p => Guid.TryParse(p.Id, out _) && !p.Name.IsEmpty() && !p.Description.IsEmpty() && p.IngredientsItems.Count > 0 && !p.OldName.IsEmpty() && !p.OldDescription.IsEmpty()), Is.True); } [Test] public void GetAllProducts_ReturnsEmptyList_Test() { // Arrange _productStorageContact.Setup(x => x.GetList()).Returns(new List()); // Act var list = _productBusinessLogicContract.GetAllProducts(); // Assert Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(0)); _productStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetAllProducts_ReturnsNull_ThrowException_Test() { // Arrange _productStorageContact.Setup(x => x.GetList()).Returns((List)null); // Act & Assert Assert.That(() => _productBusinessLogicContract.GetAllProducts(), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetAllProducts_StorageThrowError_ThrowException_Test() { // Arrange _productStorageContact.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _productBusinessLogicContract.GetAllProducts(), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetProductByData_ReturnsProductById_Test() { // Arrange var id = Guid.NewGuid().ToString(); var ingredientId = Guid.NewGuid().ToString(); var product = new ProductDataModel( id, "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.GetElementById(id)).Returns(product); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]); _productStorageContact.Setup(x => x.GetList()).Returns(new List { product }); // Act var elementById = _productBusinessLogicContract.GetProductByData(id); // Assert Assert.That(elementById, Is.Not.Null); Assert.That(elementById.Id, Is.EqualTo(id)); Assert.That(Guid.TryParse(elementById.Id, out _), Is.True); Assert.That(elementById.Name, Is.EqualTo("Updated Cake")); Assert.That(elementById.Description, Is.EqualTo("Updated delicious cake")); Assert.That(elementById.IngredientsItems.Count > 0); Assert.That(elementById.OldName, Is.EqualTo("Cake")); Assert.That(elementById.OldDescription, Is.EqualTo("Delicious cake")); _productStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); } [Test] public void GetProductByData_ReturnsProductByName_Test() { // Arrange var id = Guid.NewGuid().ToString(); var ingredientId = Guid.NewGuid().ToString(); var product = new ProductDataModel( id, "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.GetList()).Returns(new List { product }); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]); // Act var elementByName = _productBusinessLogicContract.GetProductByData("Updated Cake"); // Assert Assert.That(elementByName, Is.Not.Null); Assert.That(elementByName.Id, Is.EqualTo(id)); Assert.That(Guid.TryParse(elementByName.Id, out _), Is.True); Assert.That(elementByName.Name, Is.EqualTo("Updated Cake")); Assert.That(elementByName.Description, Is.EqualTo("Updated delicious cake")); Assert.That(elementByName.IngredientsItems.Count > 0); Assert.That(elementByName.OldName, Is.EqualTo("Cake")); Assert.That(elementByName.OldDescription, Is.EqualTo("Delicious cake")); _productStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetProductByData_ReturnsProductByOldName_Test() { // Arrange var id = Guid.NewGuid().ToString(); var ingredientId = Guid.NewGuid().ToString(); var product = new ProductDataModel( id, "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.GetList()).Returns(new List { product }); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]); // Act var elementByOldName = _productBusinessLogicContract.GetProductByData("Cake"); // Assert Assert.That(elementByOldName, Is.Not.Null); Assert.That(elementByOldName.Id, Is.EqualTo(id)); Assert.That(Guid.TryParse(elementByOldName.Id, out _), Is.True); Assert.That(elementByOldName.Name, Is.EqualTo("Updated Cake")); Assert.That(elementByOldName.Description, Is.EqualTo("Updated delicious cake")); Assert.That(elementByOldName.IngredientsItems.Count > 0); Assert.That(elementByOldName.OldName, Is.EqualTo("Cake")); Assert.That(elementByOldName.OldDescription, Is.EqualTo("Delicious cake")); _productStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetProductByData_EmptyData_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.GetProductByData(null), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.GetProductByData(string.Empty), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Never); _productStorageContact.Verify(x => x.GetList(), Times.Never); } [Test] public void GetProductByData_NotFoundProduct_ThrowException_Test() { // Arrange var id = "nonexistent"; _productStorageContact.Setup(x => x.GetElementById(id)).Returns((ProductDataModel)null); _productStorageContact.Setup(x => x.GetList()).Returns(new List()); // Act & Assert Assert.That(() => _productBusinessLogicContract.GetProductByData(id), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.GetProductByData("NonExistentProduct"), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.GetProductByData("OldNonExistent"), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); _productStorageContact.Verify(x => x.GetList(), Times.AtLeast(2)); } [Test] public void GetProductByData_StorageThrowError_ThrowException_Test() { // Arrange _productStorageContact.Setup(x => x.GetElementById(It.IsAny())).Throws(new StorageException(new InvalidOperationException())); _productStorageContact.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _productBusinessLogicContract.GetProductByData(Guid.NewGuid().ToString()), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.GetProductByData("Cake"), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.GetProductByData("OldCake"), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); _productStorageContact.Verify(x => x.GetList(), Times.AtLeast(2)); } [Test] public void InsertProduct_CorrectRecord_Test() { // Arrange var ingredientId = Guid.NewGuid().ToString(); var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; var flag = false; _productStorageContact.Setup(x => x.AddElement(It.IsAny())) .Callback((ProductDataModel x) => { flag = x.Id == product.Id && x.Name == product.Name && x.Description == product.Description && x.IngredientsItems.SequenceEqual(product.IngredientsItems) && x.OldName == product.OldName && x.OldDescription == product.OldDescription; }); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]); // Act _productBusinessLogicContract.InsertProduct(product); // Assert _productStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(product.Id, out _), Is.True); Assert.That(!product.Name.IsEmpty()); Assert.That(!product.Description.IsEmpty()); Assert.That(product.IngredientsItems.Count > 0); Assert.That( product.IngredientsItems.All(i => Guid.TryParse(i.Id, out _) && !i.Name.IsEmpty() && !i.Unit.IsEmpty() && i.Cost >= 0), Is.True); Assert.That(product.OldName, Is.EqualTo("Cake")); Assert.That(product.OldDescription, Is.EqualTo("Delicious cake")); } [Test] public void InsertProduct_RecordWithExistsData_ThrowException_Test() { // Arrange var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.AddElement(It.IsAny())) .Throws(new ElementExistsException("ID", product.Id)); // Act & Assert Assert.That(() => _productBusinessLogicContract.InsertProduct(product), Throws.TypeOf()); _productStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); } [Test] public void InsertProduct_NullRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.InsertProduct(null), Throws.TypeOf()); _productStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Never); } [Test] public void InsertProduct_InvalidRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.InsertProduct(new ProductDataModel( "", "", "", new List { new IngredientDataModel("", "", "", -100) } )), Throws.TypeOf()); _productStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Never); } [Test] public void InsertProduct_StorageThrowError_ThrowException_Test() { // Arrange var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.AddElement(It.IsAny())) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _productBusinessLogicContract.InsertProduct(product), Throws.TypeOf()); _productStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); } [Test] public void UpdateProduct_CorrectRecord_Test() { // Arrange var ingredientId = Guid.NewGuid().ToString(); var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(ingredientId, "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; var flag = false; _productStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Callback((ProductDataModel x) => { flag = x.Id == product.Id && x.Name == product.Name && x.Description == product.Description && x.IngredientsItems.SequenceEqual(product.IngredientsItems) && x.OldName == product.OldName && x.OldDescription == product.OldDescription; }); _ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]); // Act _productBusinessLogicContract.UpdateProduct(product); // Assert _productStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(product.Id, out _), Is.True); Assert.That(!product.Name.IsEmpty()); Assert.That(!product.Description.IsEmpty()); Assert.That(product.IngredientsItems.Count > 0); Assert.That( product.IngredientsItems.All(i => Guid.TryParse(i.Id, out _) && !i.Name.IsEmpty() && !i.Unit.IsEmpty() && i.Cost >= 0), Is.True); Assert.That(product.OldName, Is.EqualTo("Cake")); Assert.That(product.OldDescription, Is.EqualTo("Delicious cake")); } [Test] public void UpdateProduct_RecordNotFound_ThrowException_Test() { // Arrange var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Throws(new ElementNotFoundException("Product not found")); // Act & Assert Assert.That(() => _productBusinessLogicContract.UpdateProduct(product), Throws.TypeOf()); _productStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); } [Test] public void UpdateProduct_NullRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.UpdateProduct(null), Throws.TypeOf()); _productStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Never); } [Test] public void UpdateProduct_InvalidRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.UpdateProduct(new ProductDataModel( "", "", "", new List { new IngredientDataModel("", "", "", -100) } )), Throws.TypeOf()); _productStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Never); } [Test] public void UpdateProduct_StorageThrowError_ThrowException_Test() { // Arrange var product = new ProductDataModel( Guid.NewGuid().ToString(), "Cake", "Delicious cake", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; _productStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _productBusinessLogicContract.UpdateProduct(product), Throws.TypeOf()); _productStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); } [Test] public void DeleteProduct_CorrectId_Test() { // Arrange var id = Guid.NewGuid().ToString(); var product = new ProductDataModel( id, "Cake", "Delicious cake", new List { new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100) } ); product.Name = "Updated Cake"; product.Description = "Updated delicious cake"; var flag = false; _productStorageContact.Setup(x => x.GetElementById(id)).Returns(product); _productStorageContact.Setup(x => x.DeleteElement(id)).Callback(() => { flag = true; }); // Act _productBusinessLogicContract.DeleteProduct(id); // Assert _productStorageContact.Verify(x => x.DeleteElement(id), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(product.Id, out _), Is.True); Assert.That(!product.Name.IsEmpty()); Assert.That(!product.Description.IsEmpty()); Assert.That(product.IngredientsItems.Count > 0); Assert.That( product.IngredientsItems.All(i => Guid.TryParse(i.Id, out _) && !i.Name.IsEmpty() && !i.Unit.IsEmpty() && i.Cost >= 0), Is.True); Assert.That(product.OldName, Is.EqualTo("Cake")); Assert.That(product.OldDescription, Is.EqualTo("Delicious cake")); } [Test] public void DeleteProduct_RecordNotFound_ThrowException_Test() { // Arrange var id = "nonexistent"; _productStorageContact.Setup(x => x.GetElementById(id)).Returns((ProductDataModel)null); // Act & Assert Assert.That(() => _productBusinessLogicContract.DeleteProduct(id), Throws.TypeOf()); _productStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); } [Test] public void DeleteProduct_NullOrEmptyId_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.DeleteProduct(null), Throws.TypeOf()); Assert.That(() => _productBusinessLogicContract.DeleteProduct(string.Empty), Throws.TypeOf()); _productStorageContact.Verify(x => x.DeleteElement(It.IsAny()), Times.Never); } [Test] public void DeleteProduct_InvalidId_ThrowException_Test() { // Act & Assert Assert.That(() => _productBusinessLogicContract.DeleteProduct("invalid"), Throws.TypeOf()); _productStorageContact.Verify(x => x.DeleteElement(It.IsAny()), Times.Never); } [Test] public void DeleteProduct_StorageThrowError_ThrowException_Test() { // Arrange _productStorageContact.Setup(x => x.DeleteElement(It.IsAny())).Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _productBusinessLogicContract.DeleteProduct(Guid.NewGuid().ToString()), Throws.TypeOf()); _productStorageContact.Verify(x => x.DeleteElement(It.IsAny()), Times.Once); } } }