diff --git a/PracticeCalendar.Api/practicecalendar.sqlite b/PracticeCalendar.Api/practicecalendar.sqlite index 951caee..e0f4ddb 100644 Binary files a/PracticeCalendar.Api/practicecalendar.sqlite and b/PracticeCalendar.Api/practicecalendar.sqlite differ diff --git a/PracticeCalendar.Application/ConfigureServices.cs b/PracticeCalendar.Application/ConfigureServices.cs index 8f0013d..f7f9435 100644 --- a/PracticeCalendar.Application/ConfigureServices.cs +++ b/PracticeCalendar.Application/ConfigureServices.cs @@ -1,6 +1,9 @@ -using MapsterMapper; +using Mapster; +using MapsterMapper; using MediatR; using Microsoft.Extensions.DependencyInjection; +using PracticeCalendar.Application.PracticeEvents.Queries; +using PracticeCalendar.Domain.Entities; using System.Reflection; namespace PracticeCalendar.Application @@ -9,10 +12,25 @@ namespace PracticeCalendar.Application { public static IServiceCollection AddApplicationServices(this IServiceCollection services) { - services.AddSingleton(new Mapper(new Mapster.TypeAdapterConfig())); + services.AddMapsterMappings(); services.AddMediatR(Assembly.GetExecutingAssembly()); return services; } + + private static IServiceCollection AddMapsterMappings(this IServiceCollection services) + { + TypeAdapterConfig.GlobalSettings.Default.MapToConstructor(true); + TypeAdapterConfig.GlobalSettings.NewConfig() + .ConstructUsing(src => new PracticeEvent(src.Title, src.Description, src.StartTime, src.EndTime)); + + var mapsterConfig = new TypeAdapterConfig(); + mapsterConfig.NewConfig() + .MapToConstructor(true) + .ConstructUsing(src => new PracticeEvent(src.Title, src.Description, src.StartTime, src.EndTime)); + services.AddSingleton(new Mapper(mapsterConfig)); + + return services; + } } } diff --git a/PracticeCalendar.Application/PracticeEvents/Commands/CreatePracticeEventCommand.cs b/PracticeCalendar.Application/PracticeEvents/Commands/CreatePracticeEventCommand.cs index 81ea633..149494c 100644 --- a/PracticeCalendar.Application/PracticeEvents/Commands/CreatePracticeEventCommand.cs +++ b/PracticeCalendar.Application/PracticeEvents/Commands/CreatePracticeEventCommand.cs @@ -28,7 +28,7 @@ namespace PracticeCalendar.Application.PracticeEvents.Commands public async Task Handle(CreatePracticeEventCommand request, CancellationToken cancellationToken) { var input = request.Event; - var practiceEvent = new PracticeEvent(input.Title, input.Description); + var practiceEvent = new PracticeEvent(input.Title, input.Description, input.StartTime, input.EndTime); foreach (var att in input.Attendees) { practiceEvent.AddAttendee(new Attendee(att.Name, att.EmailAddress)); diff --git a/PracticeCalendar.Domain/Entities/PracticeEvent.cs b/PracticeCalendar.Domain/Entities/PracticeEvent.cs index 4f823dd..200fd2a 100644 --- a/PracticeCalendar.Domain/Entities/PracticeEvent.cs +++ b/PracticeCalendar.Domain/Entities/PracticeEvent.cs @@ -11,12 +11,14 @@ namespace PracticeCalendar.Domain.Entities /// public class PracticeEvent : EntityBase, IAggregateRoot { - public PracticeEvent(string title, string description) + public PracticeEvent(string title, string description, DateTime startTime, DateTime endTime) { Guard.Against.NullOrEmpty(title, nameof(title)); Guard.Against.NullOrEmpty(description, nameof(description)); this.Title = title; this.Description = description; + this.StartTime = startTime; + this.EndTime = endTime; } public string Title { get; private set; } = string.Empty; diff --git a/PracticeCalendar.Infrastructure/ConfigureServices.cs b/PracticeCalendar.Infrastructure/ConfigureServices.cs index a01c34a..0cf4eb3 100644 --- a/PracticeCalendar.Infrastructure/ConfigureServices.cs +++ b/PracticeCalendar.Infrastructure/ConfigureServices.cs @@ -18,7 +18,7 @@ namespace PracticeCalendar.Infrastructure services.AddDbContext(connectionString); services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); diff --git a/PracticeCalendar.Infrastructure/Persistence/ApplicationDbContextInitialiser.cs b/PracticeCalendar.Infrastructure/Persistence/ApplicationDbContextInitialiser.cs index 2a9c100..25f861c 100644 --- a/PracticeCalendar.Infrastructure/Persistence/ApplicationDbContextInitialiser.cs +++ b/PracticeCalendar.Infrastructure/Persistence/ApplicationDbContextInitialiser.cs @@ -56,7 +56,9 @@ namespace PracticeCalendar.Infrastructure.Persistence // Seed, if necessary if (!context.PracticeEvents.Any()) { - context.PracticeEvents.Add(new PracticeEvent("Event 1", "Event 1 desc")); + context.PracticeEvents.Add(new PracticeEvent("Event 1", "Event 1 desc", + DateTime.Now.AddHours(-1), + DateTime.Now.AddHours(1))); await context.SaveChangesAsync(); } diff --git a/PracticeCalendar.UnitTests/Application/Mapping/PracticeEventMappingTests.cs b/PracticeCalendar.UnitTests/Application/Mapping/PracticeEventMappingTests.cs new file mode 100644 index 0000000..439a205 --- /dev/null +++ b/PracticeCalendar.UnitTests/Application/Mapping/PracticeEventMappingTests.cs @@ -0,0 +1,74 @@ +using FluentAssertions; +using Mapster; +using PracticeCalendar.Application.PracticeEvents.Queries; +using PracticeCalendar.Domain.Entities; + +namespace PracticeCalendar.UnitTests.Application.Mapping +{ + public class PracticeEventMappingTests + { + readonly string _eventTitle = "Event1"; + readonly string _eventDescription = "Description"; + readonly string _attendeeName = "Claudiu Farcas"; + readonly string _attendeeEmail = "claudiu.farcas@testingbee.com"; + readonly DateTime _eventStartTime = new DateTime(2022, 10, 10, 10, 25, 35); + readonly DateTime _eventEndTime = new DateTime(2022, 10, 12, 9, 15, 00); + + public PracticeEventMappingTests() + { + TypeAdapterConfig.GlobalSettings.Default.MapToConstructor(true); + TypeAdapterConfig.GlobalSettings.NewConfig() + .ConstructUsing(src => new PracticeEvent(src.Title, src.Description, src.StartTime, src.EndTime)); + } + + [Fact] + public void PracticeEvent_to_PracticeEventDto() + { + var practiceEvent = new PracticeEvent(_eventTitle, _eventDescription, _eventStartTime, _eventEndTime); + var testAttendee = new Attendee(_attendeeName, _attendeeEmail); + practiceEvent.AddAttendee(testAttendee); + + var dto = practiceEvent.Adapt(); + + dto.Should().NotBeNull(); + dto.Title.Should().Be(_eventTitle); + dto.Description.Should().Be(_eventDescription); + dto.StartTime.Should().Be(_eventStartTime); + dto.EndTime.Should().Be(_eventEndTime); + dto.Attendees.Should().HaveCount(1); + dto.Attendees[0].Name.Should().Be(_attendeeName); + dto.Attendees[0].EmailAddress.Should().Be(_attendeeEmail); + dto.Attendees[0].IsAttending.Should().BeFalse(); + } + + [Fact] + public void PracticeEventDto_to_PracticeEvent() + { + var practiceEventDto = new PracticeEventDto + { + Title = _eventTitle, + Description = _eventDescription, + StartTime = _eventStartTime, + EndTime = _eventEndTime + }; + var attendeeDto = new AttendeeDto + { + Name = _attendeeName, + EmailAddress = _attendeeEmail + }; + practiceEventDto.Attendees.Add(attendeeDto); + + var entity = practiceEventDto.Adapt(); + + entity.Should().NotBeNull(); + entity.Title.Should().Be(_eventTitle); + entity.Description.Should().Be(_eventDescription); + entity.StartTime.Should().Be(_eventStartTime); + entity.EndTime.Should().Be(_eventEndTime); + entity.Attendees.Should().HaveCount(1); + entity.Attendees[0].Name.Should().Be(_attendeeName); + entity.Attendees[0].EmailAddress.Should().Be(_attendeeEmail); + entity.Attendees[0].IsAttending.Should().BeFalse(); + } + } +} diff --git a/PracticeCalendar.UnitTests/Domain/PracticeEventTest.cs b/PracticeCalendar.UnitTests/Domain/PracticeEventTest.cs index 15bc8a3..04ab6fd 100644 --- a/PracticeCalendar.UnitTests/Domain/PracticeEventTest.cs +++ b/PracticeCalendar.UnitTests/Domain/PracticeEventTest.cs @@ -1,4 +1,5 @@ using FluentAssertions; +using FluentAssertions.Common; using PracticeCalendar.Domain.Entities; namespace PracticeCalendar.UnitTests.Domain @@ -13,7 +14,7 @@ namespace PracticeCalendar.UnitTests.Domain [Fact] public void InitializeProperties() { - var practiceEvent = new PracticeEvent(_eventTitle, _eventDescription); + var practiceEvent = new PracticeEvent(_eventTitle, _eventDescription, DateTime.Now, DateTime.Now); practiceEvent.Title.Should().Be(_eventTitle); practiceEvent.Description.Should().Be(_eventDescription); practiceEvent.Attendees.Should().HaveCount(0); @@ -24,25 +25,25 @@ namespace PracticeCalendar.UnitTests.Domain { Action act = () => { - var practiceEvent = new PracticeEvent(null!, _eventDescription); + var practiceEvent = new PracticeEvent(null!, _eventDescription, DateTime.Now, DateTime.Now); }; act.Should().Throw(); act = () => { - var practiceEvent = new PracticeEvent(_eventTitle, null!); + var practiceEvent = new PracticeEvent(_eventTitle, null!, DateTime.Now, DateTime.Now); }; act.Should().Throw(); act = () => { - var practiceEvent = new PracticeEvent(string.Empty, _eventDescription); + var practiceEvent = new PracticeEvent(string.Empty, _eventDescription, DateTime.Now, DateTime.Now); }; act.Should().Throw(); act = () => { - var practiceEvent = new PracticeEvent(_eventTitle, string.Empty); + var practiceEvent = new PracticeEvent(_eventTitle, string.Empty, DateTime.Now, DateTime.Now); }; act.Should().Throw(); } @@ -50,7 +51,7 @@ namespace PracticeCalendar.UnitTests.Domain [Fact] public void AddAttendeeToEvent() { - var practiceEvent = new PracticeEvent(_eventTitle, _eventDescription); + var practiceEvent = new PracticeEvent(_eventTitle, _eventDescription, DateTime.Now, DateTime.Now); var testAttendee = new Attendee(_attendeeName, _atendeeEmail); practiceEvent.AddAttendee(testAttendee); practiceEvent.Attendees.Should().HaveCount(1); diff --git a/PracticeCalendar.UnitTests/Integration/CustomWebApplicationFactory.cs b/PracticeCalendar.UnitTests/Integration/CustomWebApplicationFactory.cs index 5130742..a4552a2 100644 --- a/PracticeCalendar.UnitTests/Integration/CustomWebApplicationFactory.cs +++ b/PracticeCalendar.UnitTests/Integration/CustomWebApplicationFactory.cs @@ -3,12 +3,21 @@ using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Moq; +using PracticeCalendar.Domain.Common.Interfaces; using PracticeCalendar.Infrastructure.Persistence; +using PracticeCalendar.Infrastructure.Services; namespace PracticeCalendar.UnitTests.Integration { public class CustomWebApplicationFactory : WebApplicationFactory { + private readonly Action configServices; + + public CustomWebApplicationFactory(Action configServices) + { + this.configServices = configServices; + } protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureAppConfiguration(configurationBuilder => @@ -27,7 +36,10 @@ namespace PracticeCalendar.UnitTests.Integration services.AddDbContext(options => options.UseInMemoryDatabase("InMemoryDbForTesting") ); + configServices(services); }); } + + } } diff --git a/PracticeCalendar.UnitTests/Integration/PracticeEvents/CreatePracticeEventsTest.cs b/PracticeCalendar.UnitTests/Integration/PracticeEvents/CreatePracticeEventsTest.cs index d8aaf2d..d929288 100644 --- a/PracticeCalendar.UnitTests/Integration/PracticeEvents/CreatePracticeEventsTest.cs +++ b/PracticeCalendar.UnitTests/Integration/PracticeEvents/CreatePracticeEventsTest.cs @@ -1,7 +1,8 @@ using FluentAssertions; +using Moq; using PracticeCalendar.Application.PracticeEvents.Commands; using PracticeCalendar.Application.PracticeEvents.Queries; - +using PracticeCalendar.Domain.Common; using static PracticeCalendar.UnitTests.Integration.Testing; namespace PracticeCalendar.UnitTests.Integration.PracticeEvents @@ -38,6 +39,9 @@ namespace PracticeCalendar.UnitTests.Integration.PracticeEvents result.Should().NotBeNull(); result.Id.Should().NotBe(0); result.Attendees.Count.Should().Be(2); + + //check domain events count + domainEventServiceMock.Verify(x=>x.Publish(It.IsAny()), Times.Exactly(2)); } } } diff --git a/PracticeCalendar.UnitTests/Integration/PracticeEvents/GetPracticeEventsTest.cs b/PracticeCalendar.UnitTests/Integration/PracticeEvents/GetPracticeEventsTest.cs index 586719a..24168d1 100644 --- a/PracticeCalendar.UnitTests/Integration/PracticeEvents/GetPracticeEventsTest.cs +++ b/PracticeCalendar.UnitTests/Integration/PracticeEvents/GetPracticeEventsTest.cs @@ -26,7 +26,8 @@ namespace PracticeCalendar.UnitTests.Integration.PracticeEvents { await RunBeforeAnyTests(); - await AddAsync(new PracticeEvent("Test Event", "Event description") + await AddAsync(new PracticeEvent("Test Event", "Event description", + DateTime.Now.AddHours(-1), DateTime.Now.AddHours(1)) { Id = 1, Attendees = { diff --git a/PracticeCalendar.UnitTests/Integration/Testing.cs b/PracticeCalendar.UnitTests/Integration/Testing.cs index 11c41c3..e0da9e0 100644 --- a/PracticeCalendar.UnitTests/Integration/Testing.cs +++ b/PracticeCalendar.UnitTests/Integration/Testing.cs @@ -5,6 +5,8 @@ using Microsoft.Extensions.DependencyInjection; using PracticeCalendar.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; using PracticeCalendar.Domain.Entities; +using PracticeCalendar.Domain.Common.Interfaces; +using Moq; namespace PracticeCalendar.UnitTests.Integration { @@ -14,11 +16,19 @@ namespace PracticeCalendar.UnitTests.Integration private static IConfiguration _configuration = null!; private static IServiceScopeFactory _scopeFactory = null!; + public static Mock domainEventServiceMock = null!; + public static async Task RunBeforeAnyTests() { - _factory = new CustomWebApplicationFactory(); + domainEventServiceMock = new Mock(); + + _factory = new CustomWebApplicationFactory(cfg => + { + cfg.AddSingleton(svc => domainEventServiceMock.Object); + }); + _scopeFactory = _factory.Services.GetRequiredService(); - _configuration = _factory.Services.GetRequiredService(); + _configuration = _factory.Services.GetRequiredService(); } public static async Task SendAsync(IRequest request) diff --git a/PracticeCalendar.UnitTests/PracticeCalendar.UnitTests.csproj b/PracticeCalendar.UnitTests/PracticeCalendar.UnitTests.csproj index 00e6796..c09ef81 100644 --- a/PracticeCalendar.UnitTests/PracticeCalendar.UnitTests.csproj +++ b/PracticeCalendar.UnitTests/PracticeCalendar.UnitTests.csproj @@ -41,10 +41,6 @@ - - - - PreserveNewest