586 lines
26 KiB
C#
Raw Permalink Normal View History

2025-02-26 23:49:16 +04:00
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<IProductStorageContact> _productStorageContact;
private Mock<IIngredientStorageContact> _ingredientStorageContact;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_productStorageContact = new Mock<IProductStorageContact>();
_ingredientStorageContact = new Mock<IIngredientStorageContact>();
_productBusinessLogicContract = new ProductBusinessLogicContract(
_productStorageContact.Object,
_ingredientStorageContact.Object,
new Mock<ILogger>().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<IngredientDataModel>
{
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<IngredientDataModel>
{
new IngredientDataModel(Guid.NewGuid().ToString(), "Flour", "kg", 200)
}
);
product2.Name = "Updated Pastry";
product2.Description = "Updated sweet pastry";
var products = new List<ProductDataModel> { 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<ProductDataModel>());
// 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<ProductDataModel>)null);
// Act & Assert
Assert.That(() => _productBusinessLogicContract.GetAllProducts(), Throws.TypeOf<NullListException>());
_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<StorageException>());
_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<IngredientDataModel>
{
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<ProductDataModel> { 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"));
2025-02-27 02:25:39 +04:00
_productStorageContact.Verify(x => x.GetElementById(id), Times.Once);
2025-02-26 23:49:16 +04:00
}
[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<IngredientDataModel>
{
new IngredientDataModel(ingredientId, "Sugar", "kg", 100)
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.GetList()).Returns(new List<ProductDataModel> { 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<IngredientDataModel>
{
new IngredientDataModel(ingredientId, "Sugar", "kg", 100)
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.GetList()).Returns(new List<ProductDataModel> { 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<ArgumentNullException>());
Assert.That(() => _productBusinessLogicContract.GetProductByData(string.Empty), Throws.TypeOf<ArgumentNullException>());
_productStorageContact.Verify(x => x.GetElementById(It.IsAny<string>()), Times.Never);
_productStorageContact.Verify(x => x.GetList(), Times.Never);
}
[Test]
public void GetProductByData_NotFoundProduct_ThrowException_Test()
{
// Arrange
2025-02-27 02:25:39 +04:00
var id = Guid.NewGuid().ToString();
2025-02-26 23:49:16 +04:00
_productStorageContact.Setup(x => x.GetElementById(id)).Returns((ProductDataModel)null);
_productStorageContact.Setup(x => x.GetList()).Returns(new List<ProductDataModel>());
// Act & Assert
Assert.That(() => _productBusinessLogicContract.GetProductByData(id), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _productBusinessLogicContract.GetProductByData("NonExistentProduct"), Throws.TypeOf<ElementNotFoundException>());
Assert.That(() => _productBusinessLogicContract.GetProductByData("OldNonExistent"), Throws.TypeOf<ElementNotFoundException>());
2025-02-27 02:25:39 +04:00
_productStorageContact.Verify(x => x.GetElementById(id), Times.Once);
_productStorageContact.Verify(x => x.GetList(), Times.AtLeast(2));
2025-02-26 23:49:16 +04:00
}
[Test]
public void GetProductByData_StorageThrowError_ThrowException_Test()
{
// Arrange
2025-02-27 02:25:39 +04:00
var id = Guid.NewGuid().ToString();
_productStorageContact.Setup(x => x.GetElementById(id)).Throws(new StorageException(new InvalidOperationException()));
2025-02-26 23:49:16 +04:00
_productStorageContact.Setup(x => x.GetList()).Throws(new StorageException(new InvalidOperationException()));
// Act & Assert
2025-02-27 02:25:39 +04:00
Assert.That(() => _productBusinessLogicContract.GetProductByData(id), Throws.TypeOf<StorageException>());
_productStorageContact.Verify(x => x.GetElementById(id), Times.Once);
_productStorageContact.Verify(x => x.GetList(), Times.Never);
2025-02-26 23:49:16 +04:00
}
[Test]
public void InsertProduct_CorrectRecord_Test()
{
// Arrange
var ingredientId = Guid.NewGuid().ToString();
var product = new ProductDataModel(
Guid.NewGuid().ToString(),
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
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<ProductDataModel>()))
.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<ProductDataModel>()), 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
2025-02-27 02:25:39 +04:00
var ingredientId = Guid.NewGuid().ToString();
2025-02-26 23:49:16 +04:00
var product = new ProductDataModel(
Guid.NewGuid().ToString(),
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
2025-02-27 02:25:39 +04:00
new IngredientDataModel(ingredientId, "Sugar", "kg", 100)
2025-02-26 23:49:16 +04:00
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.AddElement(It.IsAny<ProductDataModel>()))
.Throws(new ElementExistsException("ID", product.Id));
2025-02-27 02:25:39 +04:00
_ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]);
2025-02-26 23:49:16 +04:00
// Act & Assert
Assert.That(() => _productBusinessLogicContract.InsertProduct(product), Throws.TypeOf<ElementExistsException>());
_productStorageContact.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Once);
}
[Test]
public void InsertProduct_NullRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _productBusinessLogicContract.InsertProduct(null), Throws.TypeOf<ArgumentNullException>());
_productStorageContact.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Never);
}
[Test]
public void InsertProduct_InvalidRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _productBusinessLogicContract.InsertProduct(new ProductDataModel(
"",
"",
"",
new List<IngredientDataModel>
{
new IngredientDataModel("", "", "", -100)
}
)), Throws.TypeOf<ValidationException>());
_productStorageContact.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), Times.Never);
}
[Test]
public void InsertProduct_StorageThrowError_ThrowException_Test()
{
// Arrange
2025-02-27 02:25:39 +04:00
var ingredientId = Guid.NewGuid().ToString();
2025-02-26 23:49:16 +04:00
var product = new ProductDataModel(
Guid.NewGuid().ToString(),
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
2025-02-27 02:25:39 +04:00
new IngredientDataModel(ingredientId, "Sugar", "kg", 100)
2025-02-26 23:49:16 +04:00
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.AddElement(It.IsAny<ProductDataModel>()))
.Throws(new StorageException(new InvalidOperationException()));
2025-02-27 02:25:39 +04:00
_ingredientStorageContact.Setup(x => x.GetElementById(ingredientId)).Returns(product.IngredientsItems[0]);
2025-02-26 23:49:16 +04:00
// Act & Assert
Assert.That(() => _productBusinessLogicContract.InsertProduct(product), Throws.TypeOf<StorageException>());
_productStorageContact.Verify(x => x.AddElement(It.IsAny<ProductDataModel>()), 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<IngredientDataModel>
{
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<ProductDataModel>()))
.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<ProductDataModel>()), 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<IngredientDataModel>
{
new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100)
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.UpdateElement(It.IsAny<ProductDataModel>()))
.Throws(new ElementNotFoundException("Product not found"));
2025-02-27 02:25:39 +04:00
_ingredientStorageContact.Setup(x => x.GetElementById(product.IngredientsItems[0].Id)).Returns(product.IngredientsItems[0]); // Mock ingredient existence
2025-02-26 23:49:16 +04:00
// Act & Assert
Assert.That(() => _productBusinessLogicContract.UpdateProduct(product), Throws.TypeOf<ElementNotFoundException>());
_productStorageContact.Verify(x => x.UpdateElement(It.IsAny<ProductDataModel>()), Times.Once);
}
[Test]
public void UpdateProduct_NullRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _productBusinessLogicContract.UpdateProduct(null), Throws.TypeOf<ArgumentNullException>());
_productStorageContact.Verify(x => x.UpdateElement(It.IsAny<ProductDataModel>()), Times.Never);
}
[Test]
public void UpdateProduct_InvalidRecord_ThrowException_Test()
{
// Act & Assert
Assert.That(() => _productBusinessLogicContract.UpdateProduct(new ProductDataModel(
"",
"",
"",
new List<IngredientDataModel>
{
new IngredientDataModel("", "", "", -100)
}
)), Throws.TypeOf<ValidationException>());
_productStorageContact.Verify(x => x.UpdateElement(It.IsAny<ProductDataModel>()), Times.Never);
}
[Test]
public void UpdateProduct_StorageThrowError_ThrowException_Test()
{
// Arrange
var product = new ProductDataModel(
Guid.NewGuid().ToString(),
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100)
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.UpdateElement(It.IsAny<ProductDataModel>()))
.Throws(new StorageException(new InvalidOperationException()));
2025-02-27 02:25:39 +04:00
_ingredientStorageContact.Setup(x => x.GetElementById(product.IngredientsItems[0].Id)).Returns(product.IngredientsItems[0]); // Mock ingredient existence
2025-02-26 23:49:16 +04:00
// Act & Assert
Assert.That(() => _productBusinessLogicContract.UpdateProduct(product), Throws.TypeOf<StorageException>());
_productStorageContact.Verify(x => x.UpdateElement(It.IsAny<ProductDataModel>()), Times.Once);
}
[Test]
public void DeleteProduct_CorrectId_Test()
{
// Arrange
var id = Guid.NewGuid().ToString();
var product = new ProductDataModel(
id,
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
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
2025-02-27 02:25:39 +04:00
var id = Guid.NewGuid().ToString(); // Use a valid Guid
2025-02-26 23:49:16 +04:00
_productStorageContact.Setup(x => x.GetElementById(id)).Returns((ProductDataModel)null);
// Act & Assert
Assert.That(() => _productBusinessLogicContract.DeleteProduct(id), Throws.TypeOf<ElementNotFoundException>());
2025-02-27 02:25:39 +04:00
_productStorageContact.Verify(x => x.GetElementById(id), Times.Once);
2025-02-26 23:49:16 +04:00
}
[Test]
public void DeleteProduct_InvalidId_ThrowException_Test()
{
2025-02-27 02:25:39 +04:00
// Arrange
var id = "invalid";
// No need to setup GetElementById for invalid ID since validation should occur first
2025-02-26 23:49:16 +04:00
// Act & Assert
2025-02-27 02:25:39 +04:00
Assert.That(() => _productBusinessLogicContract.DeleteProduct(id), Throws.TypeOf<ValidationException>());
_productStorageContact.Verify(x => x.GetElementById(id), Times.Never); // Should not call GetElementById for invalid GUID
2025-02-26 23:49:16 +04:00
}
[Test]
public void DeleteProduct_StorageThrowError_ThrowException_Test()
{
// Arrange
2025-02-27 02:25:39 +04:00
var id = Guid.NewGuid().ToString();
var product = new ProductDataModel(
id,
"Cake",
"Delicious cake",
new List<IngredientDataModel>
{
new IngredientDataModel(Guid.NewGuid().ToString(), "Sugar", "kg", 100)
}
);
product.Name = "Updated Cake";
product.Description = "Updated delicious cake";
_productStorageContact.Setup(x => x.GetElementById(id)).Returns(product);
_productStorageContact.Setup(x => x.DeleteElement(id))
.Throws(new StorageException(new InvalidOperationException()));
2025-02-26 23:49:16 +04:00
// Act & Assert
2025-02-27 02:25:39 +04:00
Assert.That(() => _productBusinessLogicContract.DeleteProduct(id), Throws.TypeOf<StorageException>());
_productStorageContact.Verify(x => x.GetElementById(id), Times.Once);
_productStorageContact.Verify(x => x.DeleteElement(id), Times.Once);
2025-02-26 23:49:16 +04:00
}
}
}