0
0
mirror of https://github.com/alex289/CleanArchitecture.git synced 2025-06-29 18:21:08 +00:00

chore: Move properties over ctor

This commit is contained in:
alex289 2023-08-31 18:19:17 +02:00
parent a04cc8bdd0
commit 9ba530417c
No known key found for this signature in database
GPG Key ID: 573F77CD2D87F863
45 changed files with 182 additions and 182 deletions

View File

@ -10,6 +10,9 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Tenants;
public sealed class GetAllTenantsTestFixture : QueryHandlerBaseFixture public sealed class GetAllTenantsTestFixture : QueryHandlerBaseFixture
{ {
public GetAllTenantsQueryHandler QueryHandler { get; }
private ITenantRepository TenantRepository { get; }
public GetAllTenantsTestFixture() public GetAllTenantsTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -17,9 +20,6 @@ public sealed class GetAllTenantsTestFixture : QueryHandlerBaseFixture
QueryHandler = new GetAllTenantsQueryHandler(TenantRepository); QueryHandler = new GetAllTenantsQueryHandler(TenantRepository);
} }
public GetAllTenantsQueryHandler QueryHandler { get; }
private ITenantRepository TenantRepository { get; }
public Tenant SetupTenant(bool deleted = false) public Tenant SetupTenant(bool deleted = false)
{ {
var tenant = new Tenant(Guid.NewGuid(), "Tenant 1"); var tenant = new Tenant(Guid.NewGuid(), "Tenant 1");

View File

@ -10,6 +10,9 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Tenants;
public sealed class GetTenantByIdTestFixture : QueryHandlerBaseFixture public sealed class GetTenantByIdTestFixture : QueryHandlerBaseFixture
{ {
public GetTenantByIdQueryHandler QueryHandler { get; }
private ITenantRepository TenantRepository { get; }
public GetTenantByIdTestFixture() public GetTenantByIdTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -19,9 +22,6 @@ public sealed class GetTenantByIdTestFixture : QueryHandlerBaseFixture
Bus); Bus);
} }
public GetTenantByIdQueryHandler QueryHandler { get; }
private ITenantRepository TenantRepository { get; }
public Tenant SetupTenant(bool deleted = false) public Tenant SetupTenant(bool deleted = false)
{ {
var tenant = new Tenant(Guid.NewGuid(), "Tenant 1"); var tenant = new Tenant(Guid.NewGuid(), "Tenant 1");

View File

@ -10,6 +10,10 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users;
public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture
{ {
private IUserRepository UserRepository { get; }
public GetAllUsersQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public GetAllUsersTestFixture() public GetAllUsersTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -17,10 +21,6 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture
Handler = new GetAllUsersQueryHandler(UserRepository); Handler = new GetAllUsersQueryHandler(UserRepository);
} }
private IUserRepository UserRepository { get; }
public GetAllUsersQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public void SetupUserAsync() public void SetupUserAsync()
{ {
var user = new User( var user = new User(

View File

@ -11,6 +11,10 @@ namespace CleanArchitecture.Application.Tests.Fixtures.Queries.Users;
public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture
{ {
private IUserRepository UserRepository { get; }
public GetUserByIdQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public GetUserByIdTestFixture() public GetUserByIdTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -18,10 +22,6 @@ public sealed class GetUserByIdTestFixture : QueryHandlerBaseFixture
Handler = new GetUserByIdQueryHandler(UserRepository, Bus); Handler = new GetUserByIdQueryHandler(UserRepository, Bus);
} }
private IUserRepository UserRepository { get; }
public GetUserByIdQueryHandler Handler { get; }
public Guid ExistingUserId { get; } = Guid.NewGuid();
public void SetupUserAsync() public void SetupUserAsync()
{ {
var user = new User( var user = new User(

View File

@ -8,6 +8,10 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.Tenant.CreateTenant;
public sealed class CreateTenantCommandTestFixture : CommandHandlerFixtureBase public sealed class CreateTenantCommandTestFixture : CommandHandlerFixtureBase
{ {
public CreateTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
public CreateTenantCommandTestFixture() public CreateTenantCommandTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -20,10 +24,6 @@ public sealed class CreateTenantCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
public CreateTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
public void SetupUser() public void SetupUser()
{ {
User.GetUserRole().Returns(UserRole.User); User.GetUserRole().Returns(UserRole.User);

View File

@ -8,6 +8,11 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.Tenant.DeleteTenant;
public sealed class DeleteTenantCommandTestFixture : CommandHandlerFixtureBase public sealed class DeleteTenantCommandTestFixture : CommandHandlerFixtureBase
{ {
public DeleteTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
private IUserRepository UserRepository { get; }
public DeleteTenantCommandTestFixture() public DeleteTenantCommandTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -22,11 +27,6 @@ public sealed class DeleteTenantCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
public DeleteTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
private IUserRepository UserRepository { get; }
public Entities.Tenant SetupTenant() public Entities.Tenant SetupTenant()
{ {
var tenant = new Entities.Tenant(Guid.NewGuid(), "TestTenant"); var tenant = new Entities.Tenant(Guid.NewGuid(), "TestTenant");
@ -37,7 +37,7 @@ public sealed class DeleteTenantCommandTestFixture : CommandHandlerFixtureBase
return tenant; return tenant;
} }
public void SetupUser() public void SetupUser()
{ {
User.GetUserRole().Returns(UserRole.User); User.GetUserRole().Returns(UserRole.User);

View File

@ -8,6 +8,10 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.Tenant.UpdateTenant;
public sealed class UpdateTenantCommandTestFixture : CommandHandlerFixtureBase public sealed class UpdateTenantCommandTestFixture : CommandHandlerFixtureBase
{ {
public UpdateTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
public UpdateTenantCommandTestFixture() public UpdateTenantCommandTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -20,10 +24,6 @@ public sealed class UpdateTenantCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
public UpdateTenantCommandHandler CommandHandler { get; }
private ITenantRepository TenantRepository { get; }
public void SetupUser() public void SetupUser()
{ {
User.GetUserRole().Returns(UserRole.User); User.GetUserRole().Returns(UserRole.User);

View File

@ -9,6 +9,9 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.User.ChangePassword;
public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase
{ {
public ChangePasswordCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
public ChangePasswordCommandTestFixture() public ChangePasswordCommandTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -21,9 +24,6 @@ public sealed class ChangePasswordCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
public ChangePasswordCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
public Entities.User SetupUser() public Entities.User SetupUser()
{ {
var user = new Entities.User( var user = new Entities.User(

View File

@ -9,6 +9,11 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.User.CreateUser;
public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase
{ {
public CreateUserCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
private ITenantRepository TenantRepository { get; }
private IUser User { get; }
public CreateUserCommandTestFixture() public CreateUserCommandTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -24,12 +29,6 @@ public sealed class CreateUserCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
// Todo: Properties over ctor
public CreateUserCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
private ITenantRepository TenantRepository { get; }
private IUser User { get; }
public Entities.User SetupUser() public Entities.User SetupUser()
{ {
var user = new Entities.User( var user = new Entities.User(

View File

@ -8,6 +8,9 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.User.DeleteUser;
public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase
{ {
public DeleteUserCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
public DeleteUserCommandTestFixture() public DeleteUserCommandTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -20,9 +23,6 @@ public sealed class DeleteUserCommandTestFixture : CommandHandlerFixtureBase
User); User);
} }
public DeleteUserCommandHandler CommandHandler { get; }
private IUserRepository UserRepository { get; }
public Entities.User SetupUser() public Entities.User SetupUser()
{ {
var user = new Entities.User( var user = new Entities.User(

View File

@ -11,6 +11,10 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.User.LoginUser;
public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase
{ {
public LoginUserCommandHandler CommandHandler { get; set; }
public IUserRepository UserRepository { get; set; }
public IOptions<TokenSettings> TokenSettings { get; set; }
public LoginUserCommandTestFixture() public LoginUserCommandTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -30,10 +34,6 @@ public sealed class LoginUserCommandTestFixture : CommandHandlerFixtureBase
TokenSettings); TokenSettings);
} }
public LoginUserCommandHandler CommandHandler { get; set; }
public IUserRepository UserRepository { get; set; }
public IOptions<TokenSettings> TokenSettings { get; set; }
public Entities.User SetupUser() public Entities.User SetupUser()
{ {
var user = new Entities.User( var user = new Entities.User(

View File

@ -48,7 +48,7 @@ public sealed class UpdateUserCommandHandlerTests
"Email", "Email",
UserRole.User, UserRole.User,
Guid.NewGuid()); Guid.NewGuid());
_fixture.SetupTenant(command.TenantId); _fixture.SetupTenant(command.TenantId);
await _fixture.CommandHandler.Handle(command, default); await _fixture.CommandHandler.Handle(command, default);
@ -74,7 +74,7 @@ public sealed class UpdateUserCommandHandlerTests
"Email", "Email",
UserRole.User, UserRole.User,
Guid.NewGuid()); Guid.NewGuid());
_fixture.SetupTenant(command.TenantId); _fixture.SetupTenant(command.TenantId);
_fixture.UserRepository _fixture.UserRepository
@ -98,7 +98,7 @@ public sealed class UpdateUserCommandHandlerTests
DomainErrorCodes.User.UserAlreadyExists, DomainErrorCodes.User.UserAlreadyExists,
$"There is already a user with email {command.Email}"); $"There is already a user with email {command.Email}");
} }
[Fact] [Fact]
public async Task Should_Not_Update_Non_Existing_Tenant() public async Task Should_Not_Update_Non_Existing_Tenant()
{ {
@ -111,7 +111,7 @@ public sealed class UpdateUserCommandHandlerTests
"Email", "Email",
UserRole.User, UserRole.User,
Guid.NewGuid()); Guid.NewGuid());
await _fixture.CommandHandler.Handle(command, default); await _fixture.CommandHandler.Handle(command, default);
_fixture _fixture
@ -122,13 +122,13 @@ public sealed class UpdateUserCommandHandlerTests
ErrorCodes.ObjectNotFound, ErrorCodes.ObjectNotFound,
$"There is no tenant with Id {command.TenantId}"); $"There is no tenant with Id {command.TenantId}");
} }
[Fact] [Fact]
public async Task Should_Not_Update_Admin_Properties() public async Task Should_Not_Update_Admin_Properties()
{ {
var user = _fixture.SetupUser(); var user = _fixture.SetupUser();
_fixture.SetupCurrentUser(user.Id); _fixture.SetupCurrentUser(user.Id);
var command = new UpdateUserCommand( var command = new UpdateUserCommand(
user.Id, user.Id,
"test@email.com", "test@email.com",
@ -140,8 +140,8 @@ public sealed class UpdateUserCommandHandlerTests
_fixture.SetupTenant(command.TenantId); _fixture.SetupTenant(command.TenantId);
await _fixture.CommandHandler.Handle(command, default); await _fixture.CommandHandler.Handle(command, default);
_fixture.UserRepository.Received(1).Update(Arg.Is<Entities.User>(u => _fixture.UserRepository.Received(1).Update(Arg.Is<Entities.User>(u =>
u.TenantId == user.TenantId && u.TenantId == user.TenantId &&
u.Role == user.Role && u.Role == user.Role &&
u.Id == command.UserId && u.Id == command.UserId &&

View File

@ -8,6 +8,10 @@ namespace CleanArchitecture.Domain.Tests.CommandHandler.User.UpdateUser;
public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
{ {
public UpdateUserCommandHandler CommandHandler { get; }
public IUserRepository UserRepository { get; }
private ITenantRepository TenantRepository { get; }
public UpdateUserCommandTestFixture() public UpdateUserCommandTestFixture()
{ {
UserRepository = Substitute.For<IUserRepository>(); UserRepository = Substitute.For<IUserRepository>();
@ -22,10 +26,6 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
TenantRepository); TenantRepository);
} }
public UpdateUserCommandHandler CommandHandler { get; }
public IUserRepository UserRepository { get; }
private ITenantRepository TenantRepository { get; }
public Entities.User SetupUser() public Entities.User SetupUser()
{ {
var user = new Entities.User( var user = new Entities.User(
@ -47,7 +47,7 @@ public sealed class UpdateUserCommandTestFixture : CommandHandlerFixtureBase
public Entities.Tenant SetupTenant(Guid tenantId) public Entities.Tenant SetupTenant(Guid tenantId)
{ {
var tenant = new Entities.Tenant(tenantId, "Name"); var tenant = new Entities.Tenant(tenantId, "Name");
TenantRepository TenantRepository
.ExistsAsync(Arg.Is<Guid>(y => y == tenant.Id)) .ExistsAsync(Arg.Is<Guid>(y => y == tenant.Id))
.Returns(true); .Returns(true);

View File

@ -10,6 +10,11 @@ namespace CleanArchitecture.Domain.Tests;
public class CommandHandlerFixtureBase public class CommandHandlerFixtureBase
{ {
protected IMediatorHandler Bus { get; }
protected IUnitOfWork UnitOfWork { get; }
protected DomainNotificationHandler NotificationHandler { get; }
protected IUser User { get; }
protected CommandHandlerFixtureBase() protected CommandHandlerFixtureBase()
{ {
Bus = Substitute.For<IMediatorHandler>(); Bus = Substitute.For<IMediatorHandler>();
@ -23,11 +28,6 @@ public class CommandHandlerFixtureBase
UnitOfWork.CommitAsync().Returns(true); UnitOfWork.CommitAsync().Returns(true);
} }
protected IMediatorHandler Bus { get; }
protected IUnitOfWork UnitOfWork { get; }
protected DomainNotificationHandler NotificationHandler { get; }
protected IUser User { get; }
public CommandHandlerFixtureBase VerifyExistingNotification(string errorCode, string message) public CommandHandlerFixtureBase VerifyExistingNotification(string errorCode, string message)
{ {
Bus.Received(1).RaiseEventAsync( Bus.Received(1).RaiseEventAsync(

View File

@ -6,6 +6,11 @@ namespace CleanArchitecture.Domain.Commands;
public abstract class CommandBase : IRequest public abstract class CommandBase : IRequest
{ {
public Guid AggregateId { get; }
public string MessageType { get; }
public DateTime Timestamp { get; }
public ValidationResult? ValidationResult { get; protected set; }
protected CommandBase(Guid aggregateId) protected CommandBase(Guid aggregateId)
{ {
MessageType = GetType().Name; MessageType = GetType().Name;
@ -13,10 +18,5 @@ public abstract class CommandBase : IRequest
AggregateId = aggregateId; AggregateId = aggregateId;
} }
public Guid AggregateId { get; }
public string MessageType { get; }
public DateTime Timestamp { get; }
public ValidationResult? ValidationResult { get; protected set; }
public abstract bool IsValid(); public abstract bool IsValid();
} }

View File

@ -6,13 +6,13 @@ public sealed class CreateTenantCommand : CommandBase
{ {
private static readonly CreateTenantCommandValidation s_validation = new(); private static readonly CreateTenantCommandValidation s_validation = new();
public string Name { get; }
public CreateTenantCommand(Guid tenantId, string name) : base(tenantId) public CreateTenantCommand(Guid tenantId, string name) : base(tenantId)
{ {
Name = name; Name = name;
} }
public string Name { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -6,13 +6,13 @@ public sealed class UpdateTenantCommand : CommandBase
{ {
private static readonly UpdateTenantCommandValidation s_validation = new(); private static readonly UpdateTenantCommandValidation s_validation = new();
public string Name { get; }
public UpdateTenantCommand(Guid tenantId, string name) : base(tenantId) public UpdateTenantCommand(Guid tenantId, string name) : base(tenantId)
{ {
Name = name; Name = name;
} }
public string Name { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -6,15 +6,15 @@ public sealed class ChangePasswordCommand : CommandBase
{ {
private static readonly ChangePasswordCommandValidation s_validation = new(); private static readonly ChangePasswordCommandValidation s_validation = new();
public string Password { get; }
public string NewPassword { get; }
public ChangePasswordCommand(string password, string newPassword) : base(Guid.NewGuid()) public ChangePasswordCommand(string password, string newPassword) : base(Guid.NewGuid())
{ {
Password = password; Password = password;
NewPassword = newPassword; NewPassword = newPassword;
} }
public string Password { get; }
public string NewPassword { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -6,6 +6,13 @@ public sealed class CreateUserCommand : CommandBase
{ {
private static readonly CreateUserCommandValidation s_validation = new(); private static readonly CreateUserCommandValidation s_validation = new();
public Guid UserId { get; }
public Guid TenantId { get; }
public string Email { get; }
public string FirstName { get; }
public string LastName { get; }
public string Password { get; }
public CreateUserCommand( public CreateUserCommand(
Guid userId, Guid userId,
Guid tenantId, Guid tenantId,
@ -22,13 +29,6 @@ public sealed class CreateUserCommand : CommandBase
Password = password; Password = password;
} }
public Guid UserId { get; }
public Guid TenantId { get; }
public string Email { get; }
public string FirstName { get; }
public string LastName { get; }
public string Password { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -6,13 +6,13 @@ public sealed class DeleteUserCommand : CommandBase
{ {
private static readonly DeleteUserCommandValidation s_validation = new(); private static readonly DeleteUserCommandValidation s_validation = new();
public Guid UserId { get; }
public DeleteUserCommand(Guid userId) : base(userId) public DeleteUserCommand(Guid userId) : base(userId)
{ {
UserId = userId; UserId = userId;
} }
public Guid UserId { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -8,6 +8,9 @@ public sealed class LoginUserCommand : CommandBase,
{ {
private static readonly LoginUserCommandValidation s_validation = new(); private static readonly LoginUserCommandValidation s_validation = new();
public string Email { get; set; }
public string Password { get; set; }
public LoginUserCommand( public LoginUserCommand(
string email, string email,
@ -17,9 +20,6 @@ public sealed class LoginUserCommand : CommandBase,
Password = password; Password = password;
} }
public string Email { get; set; }
public string Password { get; set; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -7,6 +7,13 @@ public sealed class UpdateUserCommand : CommandBase
{ {
private static readonly UpdateUserCommandValidation s_validation = new(); private static readonly UpdateUserCommandValidation s_validation = new();
public Guid UserId { get; }
public Guid TenantId { get; }
public string Email { get; }
public string FirstName { get; }
public string LastName { get; }
public UserRole Role { get; }
public UpdateUserCommand( public UpdateUserCommand(
Guid userId, Guid userId,
string email, string email,
@ -22,13 +29,6 @@ public sealed class UpdateUserCommand : CommandBase
TenantId = tenantId; TenantId = tenantId;
} }
public Guid UserId { get; }
public Guid TenantId { get; }
public string Email { get; }
public string FirstName { get; }
public string LastName { get; }
public UserRole Role { get; }
public override bool IsValid() public override bool IsValid()
{ {
ValidationResult = s_validation.Validate(this); ValidationResult = s_validation.Validate(this);

View File

@ -13,9 +13,9 @@ namespace CleanArchitecture.Domain.Commands.Users.UpdateUser;
public sealed class UpdateUserCommandHandler : CommandHandlerBase, public sealed class UpdateUserCommandHandler : CommandHandlerBase,
IRequestHandler<UpdateUserCommand> IRequestHandler<UpdateUserCommand>
{ {
private readonly ITenantRepository _tenantRepository;
private readonly IUser _user; private readonly IUser _user;
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
private readonly ITenantRepository _tenantRepository;
public UpdateUserCommandHandler( public UpdateUserCommandHandler(
IMediatorHandler bus, IMediatorHandler bus,
@ -88,6 +88,7 @@ public sealed class UpdateUserCommandHandler : CommandHandlerBase,
ErrorCodes.ObjectNotFound)); ErrorCodes.ObjectNotFound));
return; return;
} }
user.SetTenant(request.TenantId); user.SetTenant(request.TenantId);
} }

View File

@ -5,6 +5,8 @@ namespace CleanArchitecture.Domain.DomainEvents;
public abstract class DomainEvent : Message, INotification public abstract class DomainEvent : Message, INotification
{ {
public DateTime Timestamp { get; private set; }
protected DomainEvent(Guid aggregateId) : base(aggregateId) protected DomainEvent(Guid aggregateId) : base(aggregateId)
{ {
Timestamp = DateTime.Now; Timestamp = DateTime.Now;
@ -14,6 +16,4 @@ public abstract class DomainEvent : Message, INotification
{ {
Timestamp = DateTime.Now; Timestamp = DateTime.Now;
} }
public DateTime Timestamp { get; private set; }
} }

View File

@ -5,6 +5,9 @@ namespace CleanArchitecture.Domain.DomainEvents;
public abstract class Message : IRequest public abstract class Message : IRequest
{ {
public Guid AggregateId { get; private set; }
public string MessageType { get; protected set; }
protected Message(Guid aggregateId) protected Message(Guid aggregateId)
{ {
AggregateId = aggregateId; AggregateId = aggregateId;
@ -16,7 +19,4 @@ public abstract class Message : IRequest
AggregateId = aggregateId; AggregateId = aggregateId;
MessageType = messageType ?? string.Empty; MessageType = messageType ?? string.Empty;
} }
public Guid AggregateId { get; private set; }
public string MessageType { get; protected set; }
} }

View File

@ -4,6 +4,11 @@ namespace CleanArchitecture.Domain.DomainEvents;
public class StoredDomainEvent : DomainEvent public class StoredDomainEvent : DomainEvent
{ {
public Guid Id { get; private set; }
public string Data { get; private set; } = string.Empty;
public string User { get; private set; } = string.Empty;
public string CorrelationId { get; private set; } = string.Empty;
public StoredDomainEvent( public StoredDomainEvent(
DomainEvent domainEvent, DomainEvent domainEvent,
string data, string data,
@ -21,9 +26,4 @@ public class StoredDomainEvent : DomainEvent
protected StoredDomainEvent() : base(Guid.NewGuid()) protected StoredDomainEvent() : base(Guid.NewGuid())
{ {
} }
public Guid Id { get; private set; }
public string Data { get; private set; } = string.Empty;
public string User { get; private set; } = string.Empty;
public string CorrelationId { get; private set; } = string.Empty;
} }

View File

@ -5,6 +5,11 @@ namespace CleanArchitecture.Domain.DomainNotifications;
public class StoredDomainNotification : DomainNotification public class StoredDomainNotification : DomainNotification
{ {
public Guid Id { get; private set; }
public string SerializedData { get; private set; } = string.Empty;
public string User { get; private set; } = string.Empty;
public string CorrelationId { get; private set; } = string.Empty;
public StoredDomainNotification( public StoredDomainNotification(
DomainNotification domainNotification, DomainNotification domainNotification,
string data, string data,
@ -28,9 +33,4 @@ public class StoredDomainNotification : DomainNotification
protected StoredDomainNotification() : base(string.Empty, string.Empty, string.Empty) protected StoredDomainNotification() : base(string.Empty, string.Empty, string.Empty)
{ {
} }
public Guid Id { get; private set; }
public string SerializedData { get; private set; } = string.Empty;
public string User { get; private set; } = string.Empty;
public string CorrelationId { get; private set; } = string.Empty;
} }

View File

@ -4,14 +4,14 @@ namespace CleanArchitecture.Domain.Entities;
public abstract class Entity public abstract class Entity
{ {
public Guid Id { get; private set; }
public bool Deleted { get; private set; }
protected Entity(Guid id) protected Entity(Guid id)
{ {
Id = id; Id = id;
} }
public Guid Id { get; private set; }
public bool Deleted { get; private set; }
public void SetId(Guid id) public void SetId(Guid id)
{ {
if (id == Guid.Empty) if (id == Guid.Empty)

View File

@ -5,6 +5,10 @@ namespace CleanArchitecture.Domain.Entities;
public class Tenant : Entity public class Tenant : Entity
{ {
public string Name { get; private set; }
public virtual ICollection<User> Users { get; private set; } = new HashSet<User>();
public Tenant( public Tenant(
Guid id, Guid id,
string name) : base(id) string name) : base(id)
@ -12,10 +16,6 @@ public class Tenant : Entity
Name = name; Name = name;
} }
public string Name { get; private set; }
public virtual ICollection<User> Users { get; private set; } = new HashSet<User>();
public void SetName(string name) public void SetName(string name)
{ {
Name = name; Name = name;

View File

@ -5,6 +5,17 @@ namespace CleanArchitecture.Domain.Entities;
public class User : Entity public class User : Entity
{ {
public string Email { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Password { get; private set; }
public UserRole Role { get; private set; }
public string FullName => $"{FirstName}, {LastName}";
public Guid TenantId { get; private set; }
public virtual Tenant Tenant { get; private set; } = null!;
public User( public User(
Guid id, Guid id,
Guid tenantId, Guid tenantId,
@ -22,17 +33,6 @@ public class User : Entity
Role = role; Role = role;
} }
public string Email { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Password { get; private set; }
public UserRole Role { get; private set; }
public string FullName => $"{FirstName}, {LastName}";
public Guid TenantId { get; private set; }
public virtual Tenant Tenant { get; private set; } = null!;
public void SetEmail(string email) public void SetEmail(string email)
{ {
Email = email; Email = email;

View File

@ -5,10 +5,10 @@ namespace CleanArchitecture.Domain.Events.Tenant;
public sealed class TenantCreatedEvent : DomainEvent public sealed class TenantCreatedEvent : DomainEvent
{ {
public string Name { get; set; }
public TenantCreatedEvent(Guid tenantId, string name) : base(tenantId) public TenantCreatedEvent(Guid tenantId, string name) : base(tenantId)
{ {
Name = name; Name = name;
} }
public string Name { get; set; }
} }

View File

@ -5,10 +5,10 @@ namespace CleanArchitecture.Domain.Events.Tenant;
public sealed class TenantUpdatedEvent : DomainEvent public sealed class TenantUpdatedEvent : DomainEvent
{ {
public string Name { get; set; }
public TenantUpdatedEvent(Guid tenantId, string name) : base(tenantId) public TenantUpdatedEvent(Guid tenantId, string name) : base(tenantId)
{ {
Name = name; Name = name;
} }
public string Name { get; set; }
} }

View File

@ -5,6 +5,12 @@ namespace CleanArchitecture.Domain.Notifications;
public class DomainNotification : DomainEvent public class DomainNotification : DomainEvent
{ {
public string Key { get; }
public string Value { get; }
public string Code { get; }
public object? Data { get; set; }
public int Version { get; private set; } = 1;
public DomainNotification( public DomainNotification(
string key, string key,
string value, string value,
@ -19,10 +25,4 @@ public class DomainNotification : DomainEvent
Data = data; Data = data;
} }
public string Key { get; }
public string Value { get; }
public string Code { get; }
public object? Data { get; set; }
public int Version { get; private set; } = 1;
} }

View File

@ -6,13 +6,13 @@ namespace CleanArchitecture.Infrastructure.Database;
public class ApplicationDbContext : DbContext public class ApplicationDbContext : DbContext
{ {
public DbSet<User> Users { get; set; } = null!;
public DbSet<Tenant> Tenants { get; set; } = null!;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{ {
} }
public DbSet<User> Users { get; set; } = null!;
public DbSet<Tenant> Tenants { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
builder.ApplyConfiguration(new UserConfiguration()); builder.ApplyConfiguration(new UserConfiguration());

View File

@ -6,12 +6,12 @@ namespace CleanArchitecture.Infrastructure.Database;
public class DomainNotificationStoreDbContext : DbContext public class DomainNotificationStoreDbContext : DbContext
{ {
public virtual DbSet<StoredDomainNotification> StoredDomainNotifications { get; set; } = null!;
public DomainNotificationStoreDbContext(DbContextOptions<DomainNotificationStoreDbContext> options) : base(options) public DomainNotificationStoreDbContext(DbContextOptions<DomainNotificationStoreDbContext> options) : base(options)
{ {
} }
public virtual DbSet<StoredDomainNotification> StoredDomainNotifications { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);

View File

@ -6,12 +6,12 @@ namespace CleanArchitecture.Infrastructure.Database;
public class EventStoreDbContext : DbContext public class EventStoreDbContext : DbContext
{ {
public virtual DbSet<StoredDomainEvent> StoredDomainEvents { get; set; } = null!;
public EventStoreDbContext(DbContextOptions<EventStoreDbContext> options) : base(options) public EventStoreDbContext(DbContextOptions<EventStoreDbContext> options) : base(options)
{ {
} }
public virtual DbSet<StoredDomainEvent> StoredDomainEvents { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
modelBuilder.ApplyConfiguration(new StoredDomainEventConfiguration()); modelBuilder.ApplyConfiguration(new StoredDomainEventConfiguration());

View File

@ -25,7 +25,7 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
{ {
_fixture = fixture; _fixture = fixture;
} }
[Fact] [Fact]
[Priority(0)] [Priority(0)]
public async Task Should_Get_All_User() public async Task Should_Get_All_User()
@ -49,21 +49,21 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
currentUser.FirstName.Should().Be(TestAuthenticationOptions.FirstName); currentUser.FirstName.Should().Be(TestAuthenticationOptions.FirstName);
currentUser.LastName.Should().Be(TestAuthenticationOptions.LastName); currentUser.LastName.Should().Be(TestAuthenticationOptions.LastName);
} }
[Fact] [Fact]
[Priority(5)] [Priority(5)]
public async Task Should_Get_User_By_Id() public async Task Should_Get_User_By_Id()
{ {
var response = await _fixture.ServerClient.GetAsync("/api/v1/user/" + TestAuthenticationOptions.TestUserId); var response = await _fixture.ServerClient.GetAsync("/api/v1/user/" + TestAuthenticationOptions.TestUserId);
response.StatusCode.Should().Be(HttpStatusCode.OK); response.StatusCode.Should().Be(HttpStatusCode.OK);
var message = await response.Content.ReadAsJsonAsync<UserViewModel>(); var message = await response.Content.ReadAsJsonAsync<UserViewModel>();
message?.Data.Should().NotBeNull(); message?.Data.Should().NotBeNull();
var content = message!.Data!; var content = message!.Data!;
content.Id.Should().Be(TestAuthenticationOptions.TestUserId); content.Id.Should().Be(TestAuthenticationOptions.TestUserId);
content.Email.Should().Be(TestAuthenticationOptions.Email); content.Email.Should().Be(TestAuthenticationOptions.Email);
content.FirstName.Should().Be(TestAuthenticationOptions.FirstName); content.FirstName.Should().Be(TestAuthenticationOptions.FirstName);
@ -148,18 +148,18 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
var content = message!.Data; var content = message!.Data;
content.Should().BeEquivalentTo(user); content.Should().BeEquivalentTo(user);
// Check if user is really updated // Check if user is really updated
var userResponse = await _fixture.ServerClient.GetAsync("/api/v1/user/" + user.Id); var userResponse = await _fixture.ServerClient.GetAsync("/api/v1/user/" + user.Id);
userResponse.StatusCode.Should().Be(HttpStatusCode.OK); userResponse.StatusCode.Should().Be(HttpStatusCode.OK);
var userMessage = await userResponse.Content.ReadAsJsonAsync<UserViewModel>(); var userMessage = await userResponse.Content.ReadAsJsonAsync<UserViewModel>();
userMessage?.Data.Should().NotBeNull(); userMessage?.Data.Should().NotBeNull();
var userContent = userMessage!.Data!; var userContent = userMessage!.Data!;
userContent.Id.Should().Be(user.Id); userContent.Id.Should().Be(user.Id);
userContent.Email.Should().Be(user.Email); userContent.Email.Should().Be(user.Email);
userContent.FirstName.Should().Be(user.FirstName); userContent.FirstName.Should().Be(user.FirstName);
@ -217,7 +217,7 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
content.Should().Be(TestAuthenticationOptions.TestUserId); content.Should().Be(TestAuthenticationOptions.TestUserId);
var userResponse = await _fixture.ServerClient.GetAsync("/api/v1/user/" + TestAuthenticationOptions.TestUserId); var userResponse = await _fixture.ServerClient.GetAsync("/api/v1/user/" + TestAuthenticationOptions.TestUserId);
userResponse.StatusCode.Should().Be(HttpStatusCode.NotFound); userResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
} }
} }

View File

@ -11,7 +11,7 @@ public sealed class TenantTestFixture : TestFixtureBase
protected override void SeedTestData(ApplicationDbContext context) protected override void SeedTestData(ApplicationDbContext context)
{ {
base.SeedTestData(context); base.SeedTestData(context);
context.Tenants.Add(new Tenant( context.Tenants.Add(new Tenant(
CreatedTenantId, CreatedTenantId,
"Test Tenant")); "Test Tenant"));

View File

@ -13,6 +13,9 @@ namespace CleanArchitecture.IntegrationTests.Fixtures;
public class TestFixtureBase public class TestFixtureBase
{ {
public HttpClient ServerClient { get; }
protected WebApplicationFactory<Program> Factory { get; }
public TestFixtureBase(bool useTestAuthentication = true) public TestFixtureBase(bool useTestAuthentication = true)
{ {
Factory = new CleanArchitectureWebApplicationFactory( Factory = new CleanArchitectureWebApplicationFactory(
@ -24,9 +27,6 @@ public class TestFixtureBase
ServerClient.Timeout = TimeSpan.FromMinutes(5); ServerClient.Timeout = TimeSpan.FromMinutes(5);
} }
public HttpClient ServerClient { get; }
protected WebApplicationFactory<Program> Factory { get; }
protected virtual void SeedTestData(ApplicationDbContext context) protected virtual void SeedTestData(ApplicationDbContext context)
{ {
context.Users.Add(new User( context.Users.Add(new User(

View File

@ -7,6 +7,9 @@ namespace CleanArchitecture.IntegrationTests.Fixtures.gRPC;
public sealed class GetTenantsByIdsTestFixture : TestFixtureBase public sealed class GetTenantsByIdsTestFixture : TestFixtureBase
{ {
public GrpcChannel GrpcChannel { get; }
public Guid CreatedTenantId { get; } = Guid.NewGuid();
public GetTenantsByIdsTestFixture() public GetTenantsByIdsTestFixture()
{ {
GrpcChannel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions GrpcChannel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
@ -15,9 +18,6 @@ public sealed class GetTenantsByIdsTestFixture : TestFixtureBase
}); });
} }
public GrpcChannel GrpcChannel { get; }
public Guid CreatedTenantId { get; } = Guid.NewGuid();
protected override void SeedTestData(ApplicationDbContext context) protected override void SeedTestData(ApplicationDbContext context)
{ {
base.SeedTestData(context); base.SeedTestData(context);

View File

@ -9,6 +9,9 @@ namespace CleanArchitecture.IntegrationTests.Fixtures.gRPC;
public sealed class GetUsersByIdsTestFixture : TestFixtureBase public sealed class GetUsersByIdsTestFixture : TestFixtureBase
{ {
public GrpcChannel GrpcChannel { get; }
public Guid CreatedUserId { get; } = Guid.NewGuid();
public GetUsersByIdsTestFixture() public GetUsersByIdsTestFixture()
{ {
GrpcChannel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions GrpcChannel = GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions
@ -17,9 +20,6 @@ public sealed class GetUsersByIdsTestFixture : TestFixtureBase
}); });
} }
public GrpcChannel GrpcChannel { get; }
public Guid CreatedUserId { get; } = Guid.NewGuid();
protected override void SeedTestData(ApplicationDbContext context) protected override void SeedTestData(ApplicationDbContext context)
{ {
base.SeedTestData(context); base.SeedTestData(context);

View File

@ -7,12 +7,12 @@ namespace CleanArchitecture.IntegrationTests.Infrastructure.Auth;
public sealed class TestAuthenticationOptions : AuthenticationSchemeOptions public sealed class TestAuthenticationOptions : AuthenticationSchemeOptions
{ {
public static Guid TestUserId = new("561e4300-94d6-4c3f-adf5-31c1bdbc64df");
public const string Email = "integration@tests.com"; public const string Email = "integration@tests.com";
public const string FirstName = "Integration"; public const string FirstName = "Integration";
public const string LastName = "Tests"; public const string LastName = "Tests";
public static Guid TestUserId = new("561e4300-94d6-4c3f-adf5-31c1bdbc64df");
public ClaimsIdentity Identity { get; } = new ClaimsIdentity( public ClaimsIdentity Identity { get; } = new(
new[] new[]
{ {
new Claim(ClaimTypes.Email, Email), new Claim(ClaimTypes.Email, Email),

View File

@ -22,10 +22,10 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
IServiceProvider scopedServices); IServiceProvider scopedServices);
private readonly AddCustomSeedDataHandler? _addCustomSeedDataHandler; private readonly AddCustomSeedDataHandler? _addCustomSeedDataHandler;
private readonly bool _addTestAuthentication;
private readonly SqliteConnection _connection = new("DataSource=:memory:"); private readonly SqliteConnection _connection = new("DataSource=:memory:");
private readonly RegisterCustomServicesHandler? _registerCustomServicesHandler; private readonly RegisterCustomServicesHandler? _registerCustomServicesHandler;
private readonly bool _addTestAuthentication;
public CleanArchitectureWebApplicationFactory( public CleanArchitectureWebApplicationFactory(
AddCustomSeedDataHandler? addCustomSeedDataHandler, AddCustomSeedDataHandler? addCustomSeedDataHandler,

View File

@ -10,6 +10,11 @@ namespace CleanArchitecture.gRPC.Tests.Fixtures;
public sealed class TenantTestFixture public sealed class TenantTestFixture
{ {
public TenantsApiImplementation TenantsApiImplementation { get; }
private ITenantRepository TenantRepository { get; }
public IEnumerable<Tenant> ExistingTenants { get; }
public TenantTestFixture() public TenantTestFixture()
{ {
TenantRepository = Substitute.For<ITenantRepository>(); TenantRepository = Substitute.For<ITenantRepository>();
@ -25,9 +30,4 @@ public sealed class TenantTestFixture
TenantsApiImplementation = new TenantsApiImplementation(TenantRepository); TenantsApiImplementation = new TenantsApiImplementation(TenantRepository);
} }
public TenantsApiImplementation TenantsApiImplementation { get; }
private ITenantRepository TenantRepository { get; }
public IEnumerable<Tenant> ExistingTenants { get; }
} }

View File

@ -11,6 +11,12 @@ namespace CleanArchitecture.gRPC.Tests.Fixtures;
public sealed class UserTestFixture public sealed class UserTestFixture
{ {
private IUserRepository UserRepository { get; } = Substitute.For<IUserRepository>();
public UsersApiImplementation UsersApiImplementation { get; }
public IEnumerable<User> ExistingUsers { get; }
public UserTestFixture() public UserTestFixture()
{ {
ExistingUsers = new List<User> ExistingUsers = new List<User>
@ -47,10 +53,4 @@ public sealed class UserTestFixture
UsersApiImplementation = new UsersApiImplementation(UserRepository); UsersApiImplementation = new UsersApiImplementation(UserRepository);
} }
private IUserRepository UserRepository { get; } = Substitute.For<IUserRepository>();
public UsersApiImplementation UsersApiImplementation { get; }
public IEnumerable<User> ExistingUsers { get; }
} }