using Moq; using NUnit.Framework; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using CandyHouseBase.DataModels; using CandyHouseBase.Enums; 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 PositionBusinessLogicContractTests { private PositionBusinessLogicContract _positionBusinessLogicContract; private Mock _positionStorageContact; [OneTimeSetUp] public void OneTimeSetUp() { _positionStorageContact = new Mock(); _positionBusinessLogicContract = new PositionBusinessLogicContract( _positionStorageContact.Object, new Mock().Object ); } [SetUp] public void SetUp() { _positionStorageContact.Reset(); } [Test] public void GetAllPositions_ReturnsListOfRecords_Test() { // Arrange var positions = new List { new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ), new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Medium, "Pastry Chef" ) }; _positionStorageContact.Setup(x => x.GetList()).Returns(positions); // Act var list = _positionBusinessLogicContract.GetAllPositions(); // Assert Assert.That(list, Is.Not.Null); Assert.That(list, Is.EquivalentTo(positions)); Assert.That( list.All(p => Guid.TryParse(p.Id, out _) && !p.Title.IsEmpty() && Enum.IsDefined(typeof(PositionType), p.Type)), Is.True); } [Test] public void GetAllPositions_ReturnsEmptyList_Test() { // Arrange _positionStorageContact.Setup(x => x.GetList()).Returns(new List()); // Act var list = _positionBusinessLogicContract.GetAllPositions(); // Assert Assert.That(list, Is.Not.Null); Assert.That(list, Has.Count.EqualTo(0)); _positionStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetAllPositions_ReturnsNull_ThrowException_Test() { // Arrange _positionStorageContact.Setup(x => x.GetList()).Returns((List)null); // Act & Assert Assert.That(() => _positionBusinessLogicContract.GetAllPositions(), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetAllPositions_StorageThrowError_ThrowException_Test() { // Arrange _positionStorageContact.Setup(x => x.GetList()) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _positionBusinessLogicContract.GetAllPositions(), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetList(), Times.Once); } [Test] public void GetPositionByData_ReturnsPositionById_Test() { // Arrange var id = Guid.NewGuid().ToString(); var position = new PositionDataModel( id, PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.GetElementById(id)).Returns(position); // Act var element = _positionBusinessLogicContract.GetPositionByData(id); // Assert Assert.That(element, Is.Not.Null); Assert.That(element.Id, Is.EqualTo(id)); Assert.That(Guid.TryParse(element.Id, out _), Is.True); Assert.That(!element.Title.IsEmpty()); Assert.That(Regex.IsMatch(element.Title, @"^[A-Za-zА-Яа-яЁё\s\-]+$"), Is.True); Assert.That(Enum.IsDefined(typeof(PositionType), element.Type), Is.True); _positionStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); } [Test] public void GetPositionByData_EmptyData_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.GetPositionByData(null), Throws.TypeOf()); Assert.That(() => _positionBusinessLogicContract.GetPositionByData(string.Empty), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Never); } [Test] public void GetPositionByData_NotFoundPosition_ThrowException_Test() { // Arrange var id = Guid.NewGuid().ToString(); // Use a valid Guid to test not found scenario _positionStorageContact.Setup(x => x.GetElementById(id)).Returns((PositionDataModel)null); // Act & Assert Assert.That(() => _positionBusinessLogicContract.GetPositionByData(id), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(id), Times.Once); } [Test] public void GetPositionByData_StorageThrowError_ThrowException_Test() { // Arrange _positionStorageContact.Setup(x => x.GetElementById(It.IsAny())) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _positionBusinessLogicContract.GetPositionByData(Guid.NewGuid().ToString()), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(It.IsAny()), Times.Once); } [Test] public void InsertPosition_CorrectRecord_Test() { // Arrange var flag = false; var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.AddElement(It.IsAny())) .Callback((PositionDataModel x) => { flag = x.Id == position.Id && x.Type == position.Type && x.Title == position.Title; }); // Act _positionBusinessLogicContract.InsertPosition(position); // Assert _positionStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(position.Id, out _), Is.True); Assert.That(!position.Title.IsEmpty()); Assert.That(Regex.IsMatch(position.Title, @"^[A-Za-zА-Яа-яЁё\s\-]+$"), Is.True); Assert.That(Enum.IsDefined(typeof(PositionType), position.Type), Is.True); } [Test] public void InsertPosition_RecordWithExistsData_ThrowException_Test() { // Arrange var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.AddElement(It.IsAny())) .Throws(new ElementExistsException("ID", position.Id)); // Act & Assert Assert.That(() => _positionBusinessLogicContract.InsertPosition(position), Throws.TypeOf()); _positionStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); } [Test] public void InsertPosition_NullRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.InsertPosition(null), Throws.TypeOf()); _positionStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Never); } [Test] public void InsertPosition_InvalidRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.InsertPosition(new PositionDataModel( "", (PositionType)999, "123" )), Throws.TypeOf()); _positionStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Never); } [Test] public void InsertPosition_StorageThrowError_ThrowException_Test() { // Arrange var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.AddElement(It.IsAny())) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _positionBusinessLogicContract.InsertPosition(position), Throws.TypeOf()); _positionStorageContact.Verify(x => x.AddElement(It.IsAny()), Times.Once); } [Test] public void UpdatePosition_CorrectRecord_Test() { // Arrange var flag = false; var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Callback((PositionDataModel x) => { flag = x.Id == position.Id && x.Type == position.Type && x.Title == position.Title; }); // Act _positionBusinessLogicContract.UpdatePosition(position); // Assert _positionStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(position.Id, out _), Is.True); Assert.That(!position.Title.IsEmpty()); Assert.That(Regex.IsMatch(position.Title, @"^[A-Za-zА-Яа-яЁё\s\-]+$"), Is.True); Assert.That(Enum.IsDefined(typeof(PositionType), position.Type), Is.True); } [Test] public void UpdatePosition_RecordNotFound_ThrowException_Test() { // Arrange var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Throws(new ElementNotFoundException("Position not found")); // Act & Assert Assert.That(() => _positionBusinessLogicContract.UpdatePosition(position), Throws.TypeOf()); _positionStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); } [Test] public void UpdatePosition_NullRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.UpdatePosition(null), Throws.TypeOf()); _positionStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Never); } [Test] public void UpdatePosition_InvalidRecord_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.UpdatePosition(new PositionDataModel( "", // Invalid ID (PositionType)999, "123" )), Throws.TypeOf()); _positionStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Never); } [Test] public void UpdatePosition_StorageThrowError_ThrowException_Test() { // Arrange var position = new PositionDataModel( Guid.NewGuid().ToString(), PositionType.Cool, "Baker" ); _positionStorageContact.Setup(x => x.UpdateElement(It.IsAny())) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _positionBusinessLogicContract.UpdatePosition(position), Throws.TypeOf()); _positionStorageContact.Verify(x => x.UpdateElement(It.IsAny()), Times.Once); } [Test] public void DeletePosition_CorrectId_Test() { // Arrange var id = Guid.NewGuid().ToString(); var position = new PositionDataModel( id, PositionType.Cool, "Baker" ); var flag = false; _positionStorageContact.Setup(x => x.GetElementById(id)).Returns(position); _positionStorageContact.Setup(x => x.DeleteElement(id)).Callback(() => { flag = true; }); // Act _positionBusinessLogicContract.DeletePosition(id); // Assert _positionStorageContact.Verify(x => x.DeleteElement(id), Times.Once); Assert.That(flag); Assert.That(Guid.TryParse(position.Id, out _), Is.True); Assert.That(!position.Title.IsEmpty()); Assert.That(Regex.IsMatch(position.Title, @"^[A-Za-zА-Яа-яЁё\s\-]+$"), Is.True); Assert.That(Enum.IsDefined(typeof(PositionType), position.Type), Is.True); } [Test] public void DeletePosition_RecordNotFound_ThrowException_Test() { // Arrange var id = Guid.NewGuid().ToString(); // Use a valid Guid to test not found scenario _positionStorageContact.Setup(x => x.GetElementById(id)).Returns((PositionDataModel)null); // Act & Assert Assert.That(() => _positionBusinessLogicContract.DeletePosition(id), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(id), Times.Once); } [Test] public void DeletePosition_NullOrEmptyId_ThrowException_Test() { // Act & Assert Assert.That(() => _positionBusinessLogicContract.DeletePosition(null), Throws.TypeOf()); Assert.That(() => _positionBusinessLogicContract.DeletePosition(string.Empty), Throws.TypeOf()); _positionStorageContact.Verify(x => x.DeleteElement(It.IsAny()), Times.Never); } [Test] public void DeletePosition_InvalidId_ThrowException_Test() { // Arrange var id = "invalid"; // No need to setup GetElementById for invalid ID since validation should be after existence check // Act & Assert Assert.That(() => _positionBusinessLogicContract.DeletePosition(id), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(id), Times.Never); } [Test] public void DeletePosition_StorageThrowError_ThrowException_Test() { // Arrange var id = Guid.NewGuid().ToString(); var position = new PositionDataModel(id, PositionType.Cool, "Baker"); _positionStorageContact.Setup(x => x.GetElementById(id)).Returns(position); _positionStorageContact.Setup(x => x.DeleteElement(id)) .Throws(new StorageException(new InvalidOperationException())); // Act & Assert Assert.That(() => _positionBusinessLogicContract.DeletePosition(id), Throws.TypeOf()); _positionStorageContact.Verify(x => x.GetElementById(id), Times.Once); _positionStorageContact.Verify(x => x.DeleteElement(id), Times.Once); } } }