Jelajahi Sumber

Add TenantServiceTest

Dalibor Votruba 3 tahun lalu
induk
melakukan
f841ab8b94

+ 15 - 0
Common/qdr.app.qlbrc.common/ExceptionLibrary.cs

@@ -7,15 +7,26 @@ namespace Quadarax.Application.QLiberace.Common
 
         protected override void OnSetupCodes()
         {
+            AddCode(ExceptionsCodes.ValidationErrorsCode, ExceptionsCodes.ValidationErrorsMsg);
+
             AddCode(ExceptionsCodes.SettingsNotFoundCode, ExceptionsCodes.SettingsNotFoundMsg);
             AddCode(ExceptionsCodes.SettingsNotFoundForModuleCode, ExceptionsCodes.SettingsNotFoundForModuleMsg);
             AddCode(ExceptionsCodes.SettingsHasNoPropertyCode, ExceptionsCodes.SettingsHasNoPropertyMsg);
             AddCode(ExceptionsCodes.SettingsAlreadyExistsCode, ExceptionsCodes.SettingsAlreadyExistsMsg);
+
+
+            AddCode(ExceptionsCodes.TenantNotFoundCode, ExceptionsCodes.TenantNotFoundMsg);
+            AddCode(ExceptionsCodes.TenantAlreadyExistsCode, ExceptionsCodes.TenantAlreadyExistsMsg);
+            AddCode(ExceptionsCodes.TenantLockedCode, ExceptionsCodes.TenantLockedMsg);
+            AddCode(ExceptionsCodes.TenantDifferentContextCode, ExceptionsCodes.TenantDifferentContextMsg);
         }
 
 
         public static class ExceptionsCodes
         {
+            public const string ValidationErrorsMsg = "Validation errors follows:";
+            public const int ValidationErrorsCode = 1000;
+
             public const string SettingsNotFoundMsg = "Setting '{0}' not found fo module '{1}'";
             public const int SettingsNotFoundCode = 10000;
             public const string SettingsNotFoundForModuleMsg = "Any setting not found for module '{0}'";
@@ -29,6 +40,10 @@ namespace Quadarax.Application.QLiberace.Common
             public const int TenantNotFoundCode = 10010;
             public const string TenantAlreadyExistsMsg = "Tenant with code '{0}' already exists";
             public const int TenantAlreadyExistsCode = 10011;
+            public const string TenantLockedMsg = "Tenant with code '{0}' is LOCKED! Cannot access.";
+            public const int TenantLockedCode = 10012;
+            public const string TenantDifferentContextMsg = "Cannot update different Tenant with code '{0}' in tenant context '{1}'";
+            public const int TenantDifferentContextCode = 10013;
             
         }
 

+ 8 - 6
Common/qdr.fnd.core.test/DtoTest.cs

@@ -1,12 +1,14 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
 
 namespace qdr.fnd.core.test
 {
-    public abstract class DtoTest
+    public abstract class DtoTest<TDto> : BaseTest where TDto : IDto, new()
     {
+        protected TDto Dto { get; private set; } = default!;
+
+        protected override void OnSetup()
+        {
+            Dto = new TDto();
+        }
     }
 }

+ 22 - 0
Common/qdr.fnd.core.test/ValidatorTest.cs

@@ -0,0 +1,22 @@
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+using Quadarax.Foundation.Core.Value;
+
+namespace qdr.fnd.core.test
+{
+    public abstract class ValidatorTest<TValidator, TDto> : DtoTest<TDto> where TDto : IDto, new()
+    where TValidator : Validator<TDto>, new()
+    {
+        protected TValidator Validator { get; private set; } = null!;
+        protected ValidatorContext Context { get; private set; } = null!;
+
+        protected override void OnSetup()
+        {
+            base.OnSetup();
+            Context = new ValidatorContext();
+            Validator = new TValidator();
+        }
+        protected override void OnTearDown()
+        {
+        }
+    }
+}

+ 19 - 4
Common/qdr.fnd.core/Value/Validator.cs

@@ -5,9 +5,8 @@ using System.Linq;
 
 namespace Quadarax.Foundation.Core.Value
 {
-    public abstract class Validator
+    public abstract class Validator<TValidatingObject>
     {
-
         public IList<ValidationResult> Results { get; private set; }
         public bool IsSuccess => GetIsSuccess();
 
@@ -22,13 +21,16 @@ namespace Quadarax.Foundation.Core.Value
             Results = new List<ValidationResult>();
         }
 
-        public void Validate(object validatingObject, ValidatorContext context)
+        public void Validate(TValidatingObject validatingObject, ValidatorContext context)
         {
+            if (validatingObject == null) throw new ArgumentNullException(nameof(validatingObject));
+            if (context == null) throw new ArgumentNullException(nameof(context));
+
             Results.Clear();
             OnValidate(validatingObject, context);
         }
 
-        protected abstract void OnValidate(object validatingObject, ValidatorContext context);
+        protected abstract void OnValidate(TValidatingObject validatingObject, ValidatorContext context);
 
         public void Reset()
         {
@@ -85,6 +87,19 @@ namespace Quadarax.Foundation.Core.Value
             return true;
         }
 
+        protected bool CheckIfStringMaxLengthOverflow(string name,string value, int maxLength, ValidationResult.ValidationSeverityEnum severity, string description = "")
+        {
+            if (string.IsNullOrEmpty(value))
+                return false;
+
+            if (string.IsNullOrEmpty(description))
+                description = $"Property named '{name}' length ({maxLength}) overflow.";
+            if (value.Length <= maxLength)
+                return false;
+            Results.Add(new ValidationResult(name, severity, description));
+            return true;
+        }
+
         protected bool CheckIfCollectionEmpty(string name,IEnumerable<object> value, ValidationResult.ValidationSeverityEnum severity, string description = "")
         {
             if (value!=null && value.Any())  

+ 3 - 5
Modules/qdr.app.qlbrc.base/Dtos/TenantDto.cs

@@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
 
 namespace Quadarax.Application.QLiberace.Base.Dtos
 {
-    public class TenantRDto : QlbrcDtoTrackedWithId, IStructTenant
+    public class TenantRDto : QlbrcDtoTrackedWithId, IStructTenant, IReadDto
     {
         public string Code { get; set; } = null!;
         public string Name { get; set; } = null!;
@@ -17,15 +17,13 @@ namespace Quadarax.Application.QLiberace.Base.Dtos
         public bool IsLocked { get; set; }
     }
 
-    public class TenantWDto : QlbrcDtoWithoutId, IStructTenant
+    public class TenantWDto : QlbrcDtoWithoutId, IUpdateDto, ICreateDto
     {
         public string Code { get; set; } = null!;
         public string Name { get; set; } = null!;
-        public DateTime? LastAccess { get; set; }
-        public bool IsLocked { get; set; }
     }
 
-    public class TenantDDto : QlbrcDtoWithId
+    public class TenantDDto : QlbrcDtoWithId, IDeleteDto
     {
     }
 }

+ 17 - 0
Modules/qdr.app.qlbrc.base/Dtos/Validators/TenantValidator.cs

@@ -0,0 +1,17 @@
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Application.QLiberace.Base.Dtos.Validators
+{
+    public class TenantValidator : Validator<TenantWDto>
+    {
+        protected override void OnValidate(TenantWDto validatingObject, ValidatorContext context)
+        {
+            CheckIfEmpty("Code", validatingObject.Code, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("Code", validatingObject.Code, 20,
+                ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfEmpty("Name", validatingObject.Name, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("Name", validatingObject.Name, 200,
+                ValidationResult.ValidationSeverityEnum.Error);
+        }
+    }
+}

+ 2 - 0
Modules/qdr.app.qlbrc.base/Mapper/MapperLong.cs

@@ -11,9 +11,11 @@ namespace Quadarax.Application.QLiberace.Base.Mapper
             //TODO: make automatic
             Define<Tenant,TenantRDto>().PublicProperties().Compile();
             Define<TenantWDto, Tenant>().PublicProperties().Compile();
+            Define<TenantRDto, TenantWDto>().PublicProperties().Compile();
             
             Define<User,UserRDto>().PublicProperties().Compile();
             Define<UserWDto, User>().PublicProperties().Compile();
+            Define<UserRDto, UserWDto>().PublicProperties().Compile();
 
             /*
             DefineBiDirection<User,UserRDto>();

+ 10 - 0
Modules/qdr.app.qlbrc.base/Mapper/MapperLongExt.cs

@@ -12,6 +12,7 @@ namespace Quadarax.Application.QLiberace.Base.Mapper
             return MapperLong.Instance.Map<TDao, TDto>(dao);
         }
 
+        
         public static TDao? MapDto<TDto, TDao>(this TDto? dto)
             where TDao : class, IDao<long>, new()
             where TDto : class, IDto, new()
@@ -20,6 +21,15 @@ namespace Quadarax.Application.QLiberace.Base.Mapper
             return MapperLong.Instance.Map<TDto, TDao>(dto);
         }
 
+        public static TDtoResult? MapDto2Dto<TDto,TDtoResult>(this TDto? dto)
+            where TDto : class, IDto, new()
+            where TDtoResult : class, IDto, new()
+        {
+            if (dto == null) return null;
+            return MapperLong.Instance.Map<TDto, TDtoResult>(dto);
+        }
+
+
         public static void CopyToDto<TDto, TDao>(this TDto? @from, TDao? to)
             where TDao : class, IDao<long>, new()
             where TDto : class, IDto, new()

+ 2 - 1
Modules/qdr.app.qlbrc.base/Repositories/RepoTenant.cs

@@ -1,4 +1,5 @@
 using Quadarax.Application.QLiberace.Base.Entities;
+using Quadarax.Application.QLiberace.Common.Domain;
 using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Data.Repository;
 using Quadarax.Foundation.Core.Data.Domain;
@@ -8,7 +9,7 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
 {
     public class RepoTenant: EntityRepository<long, Tenant>
     {
-        public RepoTenant(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
+        public RepoTenant(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
         {
         }
 

+ 46 - 1
Modules/qdr.app.qlbrc.base/Services/TenantService.cs

@@ -1,12 +1,16 @@
-using Quadarax.Application.QLiberace.Base.Repositories;
+using System.ComponentModel.DataAnnotations;
+using Quadarax.Application.QLiberace.Base.Repositories;
 using Quadarax.Foundation.Core.Business;
 using Microsoft.Extensions.Logging;
 using Quadarax.Application.QLiberace.Base.Dtos;
+using Quadarax.Application.QLiberace.Base.Dtos.Validators;
 using Quadarax.Application.QLiberace.Base.Entities;
 using Quadarax.Application.QLiberace.Base.Mapper;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
 using Quadarax.Application.QLiberace.Common;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Foundation.Core.Value;
 
 namespace Quadarax.Application.QLiberace.Base.Services
 {
@@ -79,6 +83,8 @@ namespace Quadarax.Application.QLiberace.Base.Services
 
             return TryCatchBlock(() =>
             {
+                ValidateWDto(tenant);
+
                 var exists = Repository.GetByCode(tenant.Code);
                 if (exists != null) throw 
                     ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantAlreadyExistsCode, tenant.Code);
@@ -89,12 +95,34 @@ namespace Quadarax.Application.QLiberace.Base.Services
             });
         }
 
+        public ResultPlain Validate(string tenantCode)
+        {
+            if (string.IsNullOrEmpty(tenantCode)) throw new ArgumentNullException(nameof(tenantCode));
+
+            return TryCatchBlock(() =>
+            {
+                var result = Repository.GetByCode(tenantCode);
+                if (result == null) throw 
+                    ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode, "code", tenantCode);
+
+                if(result.IsLocked) throw 
+                    ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantLockedCode, tenantCode);
+
+                UpdateAccess(result);
+
+                return new ResultPlain();
+
+            });
+        }
+
         public ResultDto UpdateTenant(TenantWDto tenant)
         {
             if (tenant==null) throw new ArgumentNullException(nameof(tenant));
 
             return TryCatchBlock(() =>
             {
+                ValidateWDto(tenant);
+
                 var exists = Repository.GetByCode(tenant.Code);
                 if (exists == null) throw 
                     ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode, "code", tenant.Code);
@@ -106,6 +134,7 @@ namespace Quadarax.Application.QLiberace.Base.Services
             });
         }
 
+
         public ResultDto DeleteTenant(long tenantId)
         {
             return TryCatchBlock(() =>
@@ -127,6 +156,22 @@ namespace Quadarax.Application.QLiberace.Base.Services
             tenant.LastAccess = DateTime.Now;
             Repository.Set(tenant);
         }
+
+        private void ValidateWDto(TenantWDto tenant)
+        {
+            if (tenant == null) throw new ArgumentNullException(nameof(tenant));
+            var validator = new TenantValidator();
+            validator.Validate(tenant, new ValidatorContext());
+            if (!validator.IsSuccess) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.ValidationErrorsCode, validator.ToAggregateException());
+        }
+
+        private void ValidateSameTenant(TenantWDto tenant)
+        {
+            if (tenant == null) throw new ArgumentNullException(nameof(tenant));
+            var currentTenantCode = CurrentContext.GetContext<QlbrcContext>().TenantCode;
+            if (!string.Equals(currentTenantCode, tenant.Code, StringComparison.InvariantCulture))
+                throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantDifferentContextCode, tenant.Code, currentTenantCode!);
+        }
         #endregion
     }
 }

+ 51 - 4
Tests/qdr.app.qlbrc.base.Tests/Mapper/BaseMapperDtoTest.cs

@@ -42,16 +42,37 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Mapper
             var dtoW = new TenantWDto();
             dtoW.Code = EntityCode + "X";
             dtoW.Name = EntityName + "X";
-            dtoW.LastAccess = DateTime.Now.AddHours(2);
-            dtoW.IsLocked = !dtoR.IsLocked;
 
             // dto -> dao
             dtoW.CopyToDto(dao);
             Assert.IsNotNull(dao);
             Assert.IsNull(dtoW.GetType().GetInterface(nameof(ITracked)), $"Write possible base for {dtoW.GetType().Name} must not be ITracked");
             Assert.That(dtoW.Name, Is.EqualTo(dao?.Name), $"Dto2Dao Mapping problem '{nameof(dtoW.Name)}'");
-            Assert.That(dtoW.LastAccess, Is.EqualTo(dao?.LastAccess), $"Dto2Dao Mapping problem '{nameof(dtoW.LastAccess)}'");
-            Assert.That(dtoW.IsLocked, Is.EqualTo(dao?.IsLocked), $"Dto2Dao Mapping problem '{nameof(dtoW.IsLocked)}'");
+        }
+
+        [Test]
+        public void TenantRDto2TenantWDto()
+        {
+            var dao = new Tenant();
+            dao.Code = EntityCode;
+            dao.Name = EntityName;
+            dao.LastAccess = DateTime.Now;
+            dao.IsLocked = true;
+            SetTrackedAttributes(dao);
+
+            // dao -> dtoR
+            var dtoR = dao.Map<Tenant, TenantRDto>();
+            Assert.IsNotNull(dtoR);
+            Assert.That(dao.Id,Is.EqualTo(dtoR.Id), $"Dao2Dto Mapping problem '{nameof(dtoR.Id)}'");
+            Assert.That(dao.Name, Is.EqualTo(dtoR.Name), $"Dao2Dto Mapping problem '{nameof(dtoR.Name)}'");
+            Assert.That(dao.LastAccess, Is.EqualTo(dtoR.LastAccess), $"Dao2Dto Mapping problem '{nameof(dtoR.LastAccess)}'");
+            Assert.That(dao.IsLocked, Is.EqualTo(dtoR.IsLocked), $"Dao2Dto Mapping problem '{nameof(dtoR.IsLocked)}'");
+
+            // dtoR -> dtoW
+            var dtoW = dtoR.MapDto2Dto<TenantRDto, TenantWDto>();
+            Assert.IsNotNull(dtoW);
+            Assert.That(dtoW?.Name, Is.EqualTo(dtoR.Name), $"Dto2Dto Mapping problem '{nameof(dtoR.Name)}'");
+            Assert.That(dtoW?.Code, Is.EqualTo(dtoR.Code), $"Dto2Dto Mapping problem '{nameof(dtoR.Code)}'");
         }
 
         [Test]
@@ -81,6 +102,32 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Mapper
             Assert.That(dtoW.IsLocked, Is.EqualTo(dao?.IsLocked), $"Dto2Dao Mapping problem '{nameof(dtoW.IsLocked)}'");
         }
 
+        [Test]
+        public void UserRDto2UserWDto()
+        {
+            var dao = new User();
+            dao.LoginName = EntityCode;
+            dao.IsLocked = true;
+            SetTrackedAttributes(dao);
+
+            // dao -> dto
+            var dtoR = dao.Map<User, UserRDto>();
+            Assert.IsNotNull(dtoR);
+            Assert.That(dao.Id,Is.EqualTo(dtoR.Id), $"Dao2Dto Mapping problem '{nameof(dtoR.Id)}'");
+            Assert.That(dao.LoginName, Is.EqualTo(dtoR.LoginName), $"Dao2Dto Mapping problem '{nameof(dtoR.LoginName)}'");
+            Assert.That(dao.IsLocked, Is.EqualTo(dtoR.IsLocked), $"Dao2Dto Mapping problem '{nameof(dtoR.IsLocked)}'");
+
+            
+            // dtoR -> dtoW
+            var dtoW = dtoR.MapDto2Dto<UserRDto, UserWDto>();
+            Assert.IsNotNull(dtoW);
+            Assert.That(dtoW?.LoginName, Is.EqualTo(dtoR.LoginName), $"Dto2Dto Mapping problem '{nameof(dtoR.LoginName)}'");
+            Assert.That(dtoW?.IsLocked, Is.EqualTo(dtoR.IsLocked), $"Dto2Dto Mapping problem '{nameof(dtoR.IsLocked)}'");
+            Assert.IsNull(dtoW.GetType().GetInterface(nameof(ITracked)), $"Write possible base for {dtoW.GetType().Name} must not be ITracked");
+            Assert.That(dtoW.LoginName, Is.EqualTo(dao?.LoginName), $"Dto2Dao Mapping problem '{nameof(dtoW.LoginName)}'");
+            Assert.That(dtoW.IsLocked, Is.EqualTo(dao?.IsLocked), $"Dto2Dao Mapping problem '{nameof(dtoW.IsLocked)}'");
+        }
+
         private void SetTrackedAttributes(QlbrcEntityTracked entity)
         {
             entity.Id = EntityId;

+ 45 - 0
Tests/qdr.app.qlbrc.base.Tests/Services/Base/TenantBasedService.cs

@@ -0,0 +1,45 @@
+using qdr.fnd.core.test;
+using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Repository;
+using Quadarax.Foundation.Core.Business;
+using Quadarax.Foundation.Core.Data.Domain;
+
+namespace Quadarax.Application.QLiberace.Base.Tests.Services.Base
+{
+    public abstract class TenantBasedService<TService, TRepository> : ServiceDbContextTest<TService, TRepository, BaseInMemoryDbContext>
+        where TService : AbstractRepositoryService<TRepository>
+        where TRepository : IRepository
+    {
+        public const string TenantDefaultCode = "default";
+        public const string TenantDefaultName = "Default system tenant";
+        public const bool TenantDefaultIsLocked = false;
+
+        public const string TenantOneCode = "one";
+        public const string TenantOneName = "The one tenant";
+        public const bool TenantOneIsLocked = false;
+
+
+        protected QlbrcContext Context { get; private set; } = null!;
+
+
+        protected override void OnSetup()
+        {
+            Context = new QlbrcContext(null, TenantDefaultCode, 1);
+            base.OnSetup();
+            var repoTenant = new RepoTenant(Uow.As<IDataDomain>(), Context);
+            var tenant = repoTenant.New();
+            tenant.Code = TenantDefaultCode;
+            tenant.Name = TenantDefaultName;
+            tenant.IsLocked = TenantDefaultIsLocked;
+
+            tenant = repoTenant.New();
+            tenant.Code = TenantOneCode;
+            tenant.Name = TenantOneName;
+            tenant.IsLocked = TenantOneIsLocked;
+            repoTenant.Set(tenant);
+            Uow.Commit();
+
+        }
+    }
+}

+ 53 - 41
Tests/qdr.app.qlbrc.base.Tests/Services/SettingsServiceTest.cs

@@ -2,24 +2,24 @@
 using qdr.fnd.core.test;
 using Quadarax.Application.QLiberace.Base.Repositories;
 using Quadarax.Application.QLiberace.Base.Services;
+using Quadarax.Application.QLiberace.Base.Tests.Services.Base;
 using Quadarax.Application.QLiberace.Base.Tests.Services.Fakes;
 using Quadarax.Application.QLiberace.Common;
 using Quadarax.Application.QLiberace.Common.Domain;
 using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Data.Domain;
-using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Value.Extensions;
 #pragma warning disable CS8625
 
 namespace Quadarax.Application.QLiberace.Base.Tests.Services
 {
     [TestFixture(Category = "Srv")]
-    public class SettingsServiceTest : ServiceDbContextTest<SettingsService, RepoSetting,  BaseInMemoryDbContext>
+    public class SettingsServiceTest : TenantBasedService<SettingsService, RepoSetting>
     {
-        
+
         protected override RepoSetting GetRepository()
         {
-            return new RepoSetting(Uow.As<IDataDomain>(), new QlbrcContext(null,"default", 1));
+            return new RepoSetting(Uow.As<IDataDomain>(), Context);
         }
 
         protected override SettingsService GetService()
@@ -33,11 +33,11 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         {
             var service = GetService();
             var settings = new ModuleSettingFake();
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
-            
+
             //check if stored in database
             Uow.Commit();
             var repo = GetRepository();
@@ -56,7 +56,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
 
             // no module attribute
             var settings = new ModuleSettingWoAttributeFake();
-            var result =  service.CreateSettings<ModuleSettingWoAttributeFake>(settings);
+            var result = service.CreateSettings<ModuleSettingWoAttributeFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.False);
             Assert.That(result.Errors.Count(), Is.GreaterThan(0));
@@ -70,7 +70,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
 
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -98,13 +98,14 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(resultSettings, Is.Not.Null);
             Assert.That(resultSettings.IsSuccess, Is.False);
             Assert.That(resultSettings.Errors.Count(), Is.GreaterThan(0));
-            Assert.That(resultSettings.Errors.First().Code, Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode));
+            Assert.That(resultSettings.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode));
 
             // empty module code
             Assert.That(Assert.Throws<ArgumentNullException>(() =>
                         service.GetSettings<ModuleSettingFake>(string.Empty))
                     ?.ParamName,
-                    Is.EqualTo("moduleCode"));
+                Is.EqualTo("moduleCode"));
         }
 
         [Test]
@@ -115,7 +116,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             // create one settings
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -127,7 +128,8 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(settingGot.IsSuccess, Is.True);
             Assert.That(settingGot.Errors.Count(), Is.EqualTo(0));
             Assert.That(settingGot.Values.Count, Is.EqualTo(8));
-            Assert.That(((DateTime?)settingGot.Values["PropertyDateTimeNow"])?.ToFileShortDateTimeString(), Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
+            Assert.That(((DateTime?)settingGot.Values["PropertyDateTimeNow"])?.ToFileShortDateTimeString(),
+                Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
         }
 
         [Test]
@@ -156,22 +158,23 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         {
             var service = GetService();
 
-            
+
             // create one settings
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
 
             Uow.Commit();
 
-            var value =  service.GetSettingsValue<DateTime?>("test","PropertyDateTimeNow");
+            var value = service.GetSettingsValue<DateTime?>("test", "PropertyDateTimeNow");
             Assert.That(value, Is.Not.Null);
             Assert.That(value.IsSuccess, Is.True);
-            Assert.That(value.Errors.Count(), Is.EqualTo(0));  
-            Assert.That(((DateTime?)value.Value)?.ToFileShortDateTimeString(), Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
+            Assert.That(value.Errors.Count(), Is.EqualTo(0));
+            Assert.That(((DateTime?)value.Value)?.ToFileShortDateTimeString(),
+                Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
         }
 
         [Test]
@@ -179,11 +182,11 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         {
             var service = GetService();
 
-            
+
             // create one settings
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -250,7 +253,8 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(fail, Is.Not.Null);
             Assert.That(fail.IsSuccess, Is.False);
             Assert.That(fail.Errors.Count(), Is.EqualTo(1));
-            Assert.That(fail.Errors.First().Code, Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsAlreadyExistsCode));
+            Assert.That(fail.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsAlreadyExistsCode));
 
             // empty module code
             Assert.That(Assert.Throws<ArgumentNullException>(() =>
@@ -270,11 +274,11 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         public void UpdateSettingsOK()
         {
             var service = GetService();
-            
+
             // create one settings
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -296,8 +300,10 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(settingGot, Is.Not.Null);
             Assert.That(settingGot.IsSuccess, Is.True);
             Assert.That(settingGot.Errors.Count(), Is.EqualTo(0));
-            Assert.That(settingGot.Value.PropertyDateTimeNow?.ToFileShortDateTimeString(), Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
-            Assert.That(settingGot.Value.PropertyDateTime1.ToFileShortDateTimeString(), Is.EqualTo(settings.PropertyDateTime1.ToFileShortDateTimeString()));
+            Assert.That(settingGot.Value.PropertyDateTimeNow?.ToFileShortDateTimeString(),
+                Is.EqualTo(settings.PropertyDateTimeNow?.ToFileShortDateTimeString()));
+            Assert.That(settingGot.Value.PropertyDateTime1.ToFileShortDateTimeString(),
+                Is.EqualTo(settings.PropertyDateTime1.ToFileShortDateTimeString()));
 
 
 
@@ -307,25 +313,26 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         public void UpdateSettingsFail()
         {
             var service = GetService();
-            
+
             // create one settings
             var settings = new ModuleSettingFake();
-            
+
             Assert.That(Assert.Throws<ArgumentNullException>(() =>
-                        service.UpdateSettings<ModuleSettingFake>(null))?.ParamName,
+                    service.UpdateSettings<ModuleSettingFake>(null))?.ParamName,
                 Is.EqualTo("settings"));
 
             var fail = service.UpdateSettings<ModuleSettingFake>(settings);
             Assert.That(fail, Is.Not.Null);
             Assert.That(fail.IsSuccess, Is.False);
             Assert.That(fail.Errors.Count(), Is.EqualTo(1));
-            Assert.That(fail.Errors.First().Code, Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode));
+            Assert.That(fail.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode));
 
             // include test for attributes
             //Assert.That(Assert.Throws<InvalidOperationException>(() =>
             //        service.UpdateSettings<ModuleSettingWoAttributeFake>(new ModuleSettingWoAttributeFake()))?.Message.StartsWith("ModuleAttribute"),
             //    Is.True);
-            
+
 
         }
 
@@ -333,11 +340,11 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         public void UpdateSettingsValueOK()
         {
             var service = GetService();
-            
+
             // create one settings
             var settings = new ModuleSettingFake();
             settings.PropertyString2 = DateTime.Now.ToOADate().ToString(CultureInfo.InvariantCulture);
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -350,11 +357,12 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
 
             Uow.Commit();
-            var settingGot = service.GetSettingsValue<DateTime>("test","PropertyDateTime1");
+            var settingGot = service.GetSettingsValue<DateTime>("test", "PropertyDateTime1");
             Assert.That(settingGot, Is.Not.Null);
             Assert.That(settingGot.IsSuccess, Is.True);
             Assert.That(settingGot.Errors.Count(), Is.EqualTo(0));
-            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(), Is.EqualTo(now.ToFileShortDateTimeString()));
+            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(),
+                Is.EqualTo(now.ToFileShortDateTimeString()));
 
             result = service.UpdateSettingsValue("test", "PropertyInt", null);
 
@@ -398,11 +406,12 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
 
             Uow.Commit();
-            var settingGot = service.GetSettingsValue<DateTime>("test","PropertyDateTime1");
+            var settingGot = service.GetSettingsValue<DateTime>("test", "PropertyDateTime1");
             Assert.That(settingGot, Is.Not.Null);
             Assert.That(settingGot.IsSuccess, Is.True);
             Assert.That(settingGot.Errors.Count(), Is.EqualTo(0));
-            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(), Is.EqualTo(now.ToFileShortDateTimeString()));
+            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(),
+                Is.EqualTo(now.ToFileShortDateTimeString()));
 
             now = DateTime.Now.AddHours(1);
             result = service.AddOrUpdateSettingsValue<DateTime>("test", "PropertyDateTime1", now);
@@ -411,11 +420,12 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
             Uow.Commit();
 
-            settingGot = service.GetSettingsValue<DateTime>("test","PropertyDateTime1");
+            settingGot = service.GetSettingsValue<DateTime>("test", "PropertyDateTime1");
             Assert.That(settingGot, Is.Not.Null);
             Assert.That(settingGot.IsSuccess, Is.True);
             Assert.That(settingGot.Errors.Count(), Is.EqualTo(0));
-            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(), Is.EqualTo(now.ToFileShortDateTimeString()));
+            Assert.That(((DateTime)settingGot.Value).ToFileShortDateTimeString(),
+                Is.EqualTo(now.ToFileShortDateTimeString()));
 
         }
 
@@ -424,7 +434,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         {
             var service = GetService();
 
-            
+
             // empty module code
             Assert.That(Assert.Throws<ArgumentNullException>(() =>
                         service.AddOrUpdateSettingsValue<DateTime>(string.Empty, "foo", "value"))
@@ -445,7 +455,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
 
             // create one settings
             var settings = new ModuleSettingFake();
-            var result =  service.CreateSettings<ModuleSettingFake>(settings);
+            var result = service.CreateSettings<ModuleSettingFake>(settings);
             Assert.That(result, Is.Not.Null);
             Assert.That(result.IsSuccess, Is.True);
             Assert.That(result.Errors.Count(), Is.EqualTo(0));
@@ -459,12 +469,13 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(settingGot.Values.Count, Is.EqualTo(8));
 
         }
+
         [Test]
         public void GetSettingsValuesFail()
         {
             var service = GetService();
 
-            
+
             // empty module code
             Assert.That(Assert.Throws<ArgumentNullException>(() =>
                         service.GetSettingsValues(string.Empty, null))
@@ -482,7 +493,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         protected override void OnSetup()
         {
             base.OnSetup();
-            var repoTenant = new RepoTenant(Uow.As<IDataDomain>());
+            var repoTenant = new RepoTenant(Uow.As<IDataDomain>(),new QlbrcContext(null, "default", 1));
             var tenant = repoTenant.New();
             tenant.Code = "default";
             tenant.Name = "Default system tenant";
@@ -493,3 +504,4 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
 
     }
 }
+

+ 396 - 0
Tests/qdr.app.qlbrc.base.Tests/Services/TenantServiceTest.cs

@@ -0,0 +1,396 @@
+using qdr.fnd.core.test;
+using Quadarax.Application.QLiberace.Base.Dtos;
+using Quadarax.Application.QLiberace.Base.Mapper;
+using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Application.QLiberace.Base.Services;
+using Quadarax.Application.QLiberace.Base.Tests.Services.Base;
+using Quadarax.Application.QLiberace.Base.Tests.Services.Fakes;
+using Quadarax.Application.QLiberace.Common;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Entity;
+using Quadarax.Foundation.Core.Value;
+
+#pragma warning disable CS8625
+
+namespace Quadarax.Application.QLiberace.Base.Tests.Services
+{
+    [TestFixture(Category = "Srv")]
+    public class TenantServiceTest: TenantBasedService<TenantService, RepoTenant>
+    {
+        protected override RepoTenant GetRepository()
+        {
+            return new RepoTenant(Uow.As<IDataDomain>(), new QlbrcContext(null,"default", 1));
+        }
+
+        protected override TenantService GetService()
+        {
+            return new TenantService(GetRepository(), new ContextFake(), new LoggerFactoryFake());
+        }
+
+        [Test]
+        public void ExistsTenantOK()
+        {
+            var service = GetService();
+
+            // exists tenant
+            var result = service.ExistsTenant(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.True);
+
+            // not exists tenant
+            result = service.ExistsTenant(TenantOneCode + "x");
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.False);
+        }
+        [Test]
+        public void ExistsTenantFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.ExistsTenant(string.Empty))
+                    ?.ParamName,
+                Is.EqualTo("tenantCode"));
+        }
+        [Test]
+        public void LockOK()
+        {
+            var service = GetService();
+
+            // set tenant locked
+            var result = service.Lock(TenantOneCode, true);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            
+            Uow.Commit();
+
+            //verify tenant if locked
+            var tenant = service.GetTenant(TenantOneCode);
+            Assert.That(tenant, Is.Not.Null);
+            Assert.That(tenant.IsSuccess, Is.True);
+            Assert.That(tenant.Value, Is.Not.Null);
+            Assert.That(tenant?.Value?.IsLocked, Is.EqualTo(true));
+
+
+            // set tenant unlocked
+            result = service.Lock(TenantOneCode, false);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            
+            Uow.Commit();
+
+            //verify tenant if unlocked
+            tenant = service.GetTenant(TenantOneCode);
+            Assert.That(tenant, Is.Not.Null);
+            Assert.That(tenant.IsSuccess, Is.True);
+            Assert.That(tenant.Value, Is.Not.Null);
+            Assert.That(tenant?.Value?.IsLocked, Is.EqualTo(false));
+
+        }
+
+        [Test]
+        public void LockFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.Lock(string.Empty, true))
+                    ?.ParamName,
+                Is.EqualTo("tenantCode"));
+
+            // invalid tenant code
+            var resultTenant = service.Lock("testx", true);
+            Assert.That(resultTenant, Is.Not.Null);
+            Assert.That(resultTenant.IsSuccess, Is.False);
+            Assert.That(resultTenant.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(resultTenant.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+
+
+        }
+
+        [Test]
+        public void ValidateOK()
+        {
+            var service = GetService();
+
+            // check validate unlocked
+            var result = service.Validate(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+
+            // set tenant locked
+            var resultLock = service.Lock(TenantOneCode, true);
+            Assert.That(resultLock, Is.Not.Null);
+            Assert.That(resultLock.IsSuccess, Is.True);
+            Uow.Commit();
+
+            // check validate locked
+            result = service.Validate(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantLockedCode));
+        }
+
+        [Test]
+        public void ValidateFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.Lock(string.Empty, true))
+                    ?.ParamName,
+                Is.EqualTo("tenantCode"));
+
+            // invalid tenant code
+            var resultTenant = service.Lock("testx", true);
+            Assert.That(resultTenant, Is.Not.Null);
+            Assert.That(resultTenant.IsSuccess, Is.False);
+            Assert.That(resultTenant.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(resultTenant.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+
+
+        }
+
+
+        [Test]
+        public void GetTenantOK()
+        {
+            var service = GetService();
+
+            // get tenant by code
+            var result = service.GetTenant(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.Not.Null);
+            Assert.That(result.Value?.Code, Is.EqualTo(TenantOneCode));
+            Assert.That(result.Value?.Name, Is.EqualTo(TenantOneName));
+            Assert.That(result.Value?.IsLocked, Is.EqualTo(TenantOneIsLocked));
+
+            // get tenant by id
+            result = service.GetTenant(2);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.Not.Null);
+            Assert.That(result.Value?.Code, Is.EqualTo(TenantOneCode));
+            Assert.That(result.Value?.Name, Is.EqualTo(TenantOneName));
+            Assert.That(result.Value?.IsLocked, Is.EqualTo(TenantOneIsLocked));
+        }
+        [Test]
+        public void GetTenantFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.GetTenant(string.Empty))
+                    ?.ParamName,
+                Is.EqualTo("tenantCode"));
+
+            // get tenant by code
+            var result = service.GetTenant(TenantOneCode + "X");
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+
+            // get tenant by id
+            result = service.GetTenant(-1);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+        }
+        [Test]
+        public void CreateTenantOK()
+        {
+            var service = GetService();
+
+            var newTenant = new TenantWDto()
+            {
+                Code = "NewTenant",
+                Name = "NewTenant"
+            };
+
+            var result = service.CreateTenant(newTenant);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.Not.Null);
+            Uow.Commit();
+
+            var tenant = service.GetTenant(newTenant.Code);
+            Assert.That(tenant, Is.Not.Null);
+            Assert.That(tenant.IsSuccess, Is.True);
+            Assert.That(tenant.Value, Is.Not.Null);
+            Assert.That(tenant.Value?.Code, Is.EqualTo(newTenant.Code));
+            Assert.That(tenant.Value?.Name, Is.EqualTo(newTenant.Name));
+            Assert.That(tenant.Value?.LastAccess, Is.Not.Null);
+
+        }
+        [Test]
+        public void CreateTenantFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.CreateTenant(null))
+                    ?.ParamName,
+                Is.EqualTo("tenant"));
+
+            var newTenant = new TenantWDto()
+            {
+                Code = "NewTenant",
+                Name = "NewTenant"
+            };
+
+            // create one tenant
+            var result = service.CreateTenant(newTenant);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.Not.Null);
+            Uow.Commit();
+
+            // create same/duplicit tenant
+            result = service.CreateTenant(newTenant);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Value, Is.Not.Null);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantAlreadyExistsCode));
+
+            // create not valid tenant (code oveflow)
+            newTenant.Code = new string('x', 21);
+            result = service.CreateTenant(newTenant);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Value, Is.Not.Null);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.ValidationErrorsCode));
+        }
+        [Test]
+        public void UpdateTenantOK()
+        {
+            var service = GetService();
+
+            // gets existing tenant
+            var tenant = service.GetTenant(TenantOneCode);
+            Assert.That(tenant, Is.Not.Null);
+            Assert.That(tenant.IsSuccess, Is.True);
+            Assert.That(tenant.Value, Is.Not.Null);
+
+            //update some properties
+            var tenantW = tenant.Value.MapDto2Dto<TenantRDto, TenantWDto>();
+            Assert.That(tenantW, Is.Not.Null);
+            tenantW.Name = TenantOneName + "x";
+            var result = service.UpdateTenant(tenantW);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Errors.Count(), Is.EqualTo(0));
+
+        }
+        [Test]
+        public void UpdateTenantFail()
+        {
+            var service = GetService();
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        service.UpdateTenant(null))
+                    ?.ParamName,
+                Is.EqualTo("tenant"));
+
+            // gets existing tenant
+            var tenant = service.GetTenant(TenantOneCode);
+            Assert.That(tenant, Is.Not.Null);
+            Assert.That(tenant.IsSuccess, Is.True);
+            Assert.That(tenant.Value, Is.Not.Null);
+
+
+            //update some properties fails
+            var tenantW = tenant.Value.MapDto2Dto<TenantRDto, TenantWDto>();
+            Assert.That(tenantW, Is.Not.Null);
+            tenantW.Name = new string('x',201);
+            var result = service.UpdateTenant(tenantW);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.ValidationErrorsCode));
+
+            //update with bad tenant code
+            tenantW.Name = TenantDefaultName;
+            tenantW.Code = TenantOneCode + "x";
+            result = service.UpdateTenant(tenantW);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+        }
+        [Test]
+        public void DeleteTenantOK()
+        {
+            var service = GetService();
+
+            var result = service.GetTenant(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.True);
+            Assert.That(result.Value, Is.Not.Null);
+
+            // delete tenant
+            var delete = service.DeleteTenant(result.Value!.Id);
+            Assert.That(delete, Is.Not.Null);
+            Assert.That(delete.IsSuccess, Is.True);
+            Uow.Commit();
+
+            // verify delete
+            result = service.GetTenant(TenantOneCode);
+            Assert.That(result, Is.Not.Null);
+            Assert.That(result.IsSuccess, Is.False);
+            Assert.That(result.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(result.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+            
+        }
+        [Test]
+        public void DeleteTenantFail()
+        {
+            var service = GetService();
+
+            // delete tenant
+            var delete = service.DeleteTenant(-1);
+            Assert.That(delete, Is.Not.Null);
+            Assert.That(delete.IsSuccess, Is.False);
+            Assert.That(delete.Errors.Count(), Is.GreaterThan(0));
+            Assert.That(delete.Errors.First().Code,
+                Is.EqualTo(ExceptionLibrary.ExceptionsCodes.TenantNotFoundCode));
+
+        }
+
+        protected override void OnSetup()
+        {
+            base.OnSetup();
+            var repoTenant = new RepoTenant(Uow.As<IDataDomain>(),new QlbrcContext(null, "default", 1));
+            var tenant = repoTenant.New();
+            tenant.Code = "default";
+            tenant.Name = "Default system tenant";
+            tenant.IsLocked = false;
+            repoTenant.Set(tenant);
+            Uow.Commit();
+        }
+    }
+}

+ 58 - 0
Tests/qdr.app.qlbrc.base.Tests/Validators/TenantValidatorTest.cs

@@ -0,0 +1,58 @@
+using qdr.fnd.core.test;
+using Quadarax.Application.QLiberace.Base.Dtos;
+using Quadarax.Application.QLiberace.Base.Dtos.Validators;
+
+namespace Quadarax.Application.QLiberace.Base.Tests.Validators
+{
+    [TestFixture(Category = "Validator")]
+    public class TenantValidatorTest : ValidatorTest<TenantValidator, TenantWDto>
+    {
+        [Test]
+        public void Code()
+        {
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.True);
+            Assert.That(Validator.Results.Count, Is.EqualTo(0));
+
+            Dto.Code = string.Empty;
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.False);
+            Assert.That(Validator.Results.Count, Is.GreaterThan(0));
+            Assert.That(Validator.Results[0].Description.Contains("must be filled"), Is.True);
+
+            Dto.Code = new string('x',21);
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.False);
+            Assert.That(Validator.Results.Count, Is.GreaterThan(0));
+            Assert.That(Validator.Results[0].Description.Contains("overflow"), Is.True);
+        }
+
+        [Test]
+        public void Name()
+        {
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.True);
+            Assert.That(Validator.Results.Count, Is.EqualTo(0));
+
+            Dto.Name = string.Empty;
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.False);
+            Assert.That(Validator.Results.Count, Is.GreaterThan(0));
+            Assert.That(Validator.Results[0].Description.Contains("must be filled"), Is.True);
+
+            Dto.Name = new string('x',201);
+            Validator.Validate(Dto, Context);
+            Assert.That(Validator.IsSuccess, Is.False);
+            Assert.That(Validator.Results.Count, Is.GreaterThan(0));
+            Assert.That(Validator.Results[0].Description.Contains("overflow"), Is.True);
+
+        }
+
+        protected override void OnSetup()
+        {
+            base.OnSetup();
+            Dto.Code = "TestCode";
+            Dto.Name = "TestName";
+        }
+    }
+}