From 41add2a0230641d384f9ae9c6c1ed9eded755693 Mon Sep 17 00:00:00 2001 From: Gramli Date: Sat, 2 Mar 2024 22:25:28 +0100 Subject: [PATCH 1/3] Implementation of delete endpoint --- src/Tests/HttpDebug/debug-tests.http | 6 +- .../Domain/Dtos/CurrentWeatherDto.cs | 2 +- .../AddFavorites/AddFavoriteHandler.cs | 10 +-- .../ContainerConfigurationExtension.cs | 6 +- .../ContainerConfigurationExtension.cs | 29 +++++++++ .../DeleteFavorites/DeleteFavoriteCommand.cs | 7 +++ ...eleteFavoriteCommandSpecificationHolder.cs | 17 +++++ .../DeleteFavorites/DeleteFavoriteHandler.cs | 62 +++++++++++++++++++ .../GetFavorites/FavoriteCurrentWeatherDto.cs | 10 +++ .../GetFavorites/FavoritesWeatherDto.cs | 4 +- .../GetFavorites/GetFavoritesHandler.cs | 20 ++++-- src/Weather.API/Program.cs | 7 ++- 12 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 src/Weather.API/Features/DeleteFavorites/ContainerConfigurationExtension.cs create mode 100644 src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommand.cs create mode 100644 src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommandSpecificationHolder.cs create mode 100644 src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs create mode 100644 src/Weather.API/Features/GetFavorites/FavoriteCurrentWeatherDto.cs diff --git a/src/Tests/HttpDebug/debug-tests.http b/src/Tests/HttpDebug/debug-tests.http index b8389a1..9f9828a 100644 --- a/src/Tests/HttpDebug/debug-tests.http +++ b/src/Tests/HttpDebug/debug-tests.http @@ -23,4 +23,8 @@ Content-Type: application/json "latitude": 38.5, "longitude": -78.5 } -} \ No newline at end of file +} + +### add favorites weather request +DELETE https://{{host}}/weather/v1/favorite/1 +Content-Type: application/json \ No newline at end of file diff --git a/src/Weather.API/Domain/Dtos/CurrentWeatherDto.cs b/src/Weather.API/Domain/Dtos/CurrentWeatherDto.cs index 171de1b..7cc548f 100644 --- a/src/Weather.API/Domain/Dtos/CurrentWeatherDto.cs +++ b/src/Weather.API/Domain/Dtos/CurrentWeatherDto.cs @@ -1,6 +1,6 @@ namespace Weather.API.Domain.Dtos { - public sealed class CurrentWeatherDto + public class CurrentWeatherDto { public double Temperature { get; init; } diff --git a/src/Weather.API/Features/AddFavorites/AddFavoriteHandler.cs b/src/Weather.API/Features/AddFavorites/AddFavoriteHandler.cs index fbc2793..fdb4eba 100644 --- a/src/Weather.API/Features/AddFavorites/AddFavoriteHandler.cs +++ b/src/Weather.API/Features/AddFavorites/AddFavoriteHandler.cs @@ -13,7 +13,7 @@ namespace Weather.API.Features.Favorites.AddFavorites { - internal sealed class AddFavoriteHandler : IRequestHandler + internal sealed class AddFavoriteHandler : IRequestHandler { private readonly IMapper _mapper; private readonly WeatherContext _weatherContext; @@ -31,20 +31,20 @@ public AddFavoriteHandler( _mapper = Guard.Against.Null(mapper); } - public async Task> HandleAsync(AddFavoriteCommand request, CancellationToken cancellationToken) + public async Task> HandleAsync(AddFavoriteCommand request, CancellationToken cancellationToken) { if (!_addFavoriteCommandValidator.IsValid(request)) { - return HttpDataResponses.AsBadRequest(string.Format(ErrorMessages.RequestValidationError, request)); + return HttpDataResponses.AsBadRequest(string.Format(ErrorMessages.RequestValidationError, request)); } var addResult = await AddFavoriteLocationSafeAsync(request, cancellationToken); if (addResult.IsFailed) { - return HttpDataResponses.AsInternalServerError("Location was not stored in database."); + return HttpDataResponses.AsInternalServerError("Location was not stored in database."); } - return HttpDataResponses.AsOK(true); + return HttpDataResponses.AsOK(addResult.Value); } public async Task> AddFavoriteLocationSafeAsync(AddFavoriteCommand addFavoriteCommand, CancellationToken cancellationToken) diff --git a/src/Weather.API/Features/AddFavorites/ContainerConfigurationExtension.cs b/src/Weather.API/Features/AddFavorites/ContainerConfigurationExtension.cs index 2d8e850..a0fe864 100644 --- a/src/Weather.API/Features/AddFavorites/ContainerConfigurationExtension.cs +++ b/src/Weather.API/Features/AddFavorites/ContainerConfigurationExtension.cs @@ -12,9 +12,9 @@ public static class ContainerConfigurationExtension public static IEndpointRouteBuilder BuildAddFavoriteWeatherEndpoints(this IEndpointRouteBuilder endpointRouteBuilder) { endpointRouteBuilder.MapPost("v1/favorite", - async ([FromBody] AddFavoriteCommand addFavoriteCommand, [FromServices] IRequestHandler handler, CancellationToken cancellationToken) => + async ([FromBody] AddFavoriteCommand addFavoriteCommand, [FromServices] IRequestHandler handler, CancellationToken cancellationToken) => await handler.SendAsync(addFavoriteCommand, cancellationToken)) - .Produces>() + .Produces>() .WithName("AddFavorite") .WithTags("Setters"); @@ -23,7 +23,7 @@ await handler.SendAsync(addFavoriteCommand, cancellationToken)) public static IServiceCollection AddAddFavorites(this IServiceCollection serviceCollection) => serviceCollection - .AddScoped, AddFavoriteHandler>() + .AddScoped, AddFavoriteHandler>() .AddValidotSingleton, AddFavoriteCommandSpecificationHolder, AddFavoriteCommand>(); } diff --git a/src/Weather.API/Features/DeleteFavorites/ContainerConfigurationExtension.cs b/src/Weather.API/Features/DeleteFavorites/ContainerConfigurationExtension.cs new file mode 100644 index 0000000..b4b4210 --- /dev/null +++ b/src/Weather.API/Features/DeleteFavorites/ContainerConfigurationExtension.cs @@ -0,0 +1,29 @@ +using Microsoft.AspNetCore.Mvc; +using Validot; +using Weather.API.Domain.Abstractions; +using Weather.API.Domain.Extensions; +using WeatherApi.Domain.Http; + +namespace Weather.API.Features.DeleteFavorites +{ + public static class ContainerConfigurationExtension + { + public static IEndpointRouteBuilder BuildDeleteFavoriteWeatherEndpoints(this IEndpointRouteBuilder endpointRouteBuilder) + { + endpointRouteBuilder.MapDelete("v1/favorite/{id}", + async (int id, [FromServices] IRequestHandler handler, CancellationToken cancellationToken) => + await handler.SendAsync(new DeleteFavoriteCommand { Id = id }, cancellationToken)) + .Produces>() + .WithName("DeleteFavorite") + .WithTags("Delete"); + + return endpointRouteBuilder; + } + + public static IServiceCollection AddDeleteFavorites(this IServiceCollection serviceCollection) + => serviceCollection + .AddScoped, DeleteFavoriteHandler>() + .AddValidotSingleton, DeleteFavoriteCommandSpecificationHolder, DeleteFavoriteCommand>(); + + } +} diff --git a/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommand.cs b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommand.cs new file mode 100644 index 0000000..4f0ab2d --- /dev/null +++ b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommand.cs @@ -0,0 +1,7 @@ +namespace Weather.API.Features.DeleteFavorites +{ + internal sealed class DeleteFavoriteCommand + { + public int Id { get; init; } + } +} diff --git a/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommandSpecificationHolder.cs b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommandSpecificationHolder.cs new file mode 100644 index 0000000..edcd8ce --- /dev/null +++ b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteCommandSpecificationHolder.cs @@ -0,0 +1,17 @@ +using Validot; + +namespace Weather.API.Features.DeleteFavorites +{ + internal sealed class DeleteFavoriteCommandSpecificationHolder : ISpecificationHolder + { + public Specification Specification { get; } + + public DeleteFavoriteCommandSpecificationHolder() + { + Specification addFavoriteCommandSpecification = s => s + .Member(m => m.Id, r => r.NonNegative()); + + Specification = addFavoriteCommandSpecification; + } + } +} diff --git a/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs new file mode 100644 index 0000000..27f1e4d --- /dev/null +++ b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs @@ -0,0 +1,62 @@ +using Ardalis.GuardClauses; +using FluentResults; +using Microsoft.EntityFrameworkCore; +using Validot; +using Weather.API.Domain.Abstractions; +using Weather.API.Domain.Database.EFContext; +using Weather.API.Domain.Extensions; +using Weather.API.Domain.Logging; +using Weather.API.Domain.Resources; +using Weather.API.Features.Favorites.AddFavorites; +using WeatherApi.Domain.Http; + +namespace Weather.API.Features.DeleteFavorites +{ + internal sealed class DeleteFavoriteHandler : IRequestHandler + { + private readonly WeatherContext _weatherContext; + private readonly IValidator _validator; + private readonly ILogger _logger; + public DeleteFavoriteHandler( + IValidator validator, + ILogger logger, + WeatherContext weatherContext) + { + _validator = Guard.Against.Null(validator); + _logger = Guard.Against.Null(logger); + _weatherContext = Guard.Against.Null(weatherContext); + } + + public async Task> HandleAsync(DeleteFavoriteCommand request, CancellationToken cancellationToken) + { + if (!_validator.IsValid(request)) + { + return HttpDataResponses.AsBadRequest(string.Format(ErrorMessages.RequestValidationError, request)); + } + + var addResult = await DeleteFavoriteLocationSafeAsync(request, cancellationToken); + if (addResult.IsFailed) + { + return HttpDataResponses.AsInternalServerError("Location was not deleted from database."); + } + + return HttpDataResponses.AsOK(true); + } + + public async Task DeleteFavoriteLocationSafeAsync(DeleteFavoriteCommand command, CancellationToken cancellationToken) + { + try + { + var location = await _weatherContext.FavoriteLocations.FindAsync(command.Id, cancellationToken); + _weatherContext.Remove(location!); + await _weatherContext.SaveChangesAsync(cancellationToken); + return Result.Ok(); + } + catch (DbUpdateException ex) + { + _logger.LogError(LogEvents.FavoriteWeathersStoreToDatabase, ex, "Can't delete location."); + return Result.Fail(ex.Message); + } + } + } +} diff --git a/src/Weather.API/Features/GetFavorites/FavoriteCurrentWeatherDto.cs b/src/Weather.API/Features/GetFavorites/FavoriteCurrentWeatherDto.cs new file mode 100644 index 0000000..94ed444 --- /dev/null +++ b/src/Weather.API/Features/GetFavorites/FavoriteCurrentWeatherDto.cs @@ -0,0 +1,10 @@ + +using Weather.API.Domain.Dtos; + +namespace Weather.API.Features.GetFavorites +{ + public sealed class FavoriteCurrentWeatherDto : CurrentWeatherDto + { + public int Id { get; init; } + } +} diff --git a/src/Weather.API/Features/GetFavorites/FavoritesWeatherDto.cs b/src/Weather.API/Features/GetFavorites/FavoritesWeatherDto.cs index 062bdf8..680a2ca 100644 --- a/src/Weather.API/Features/GetFavorites/FavoritesWeatherDto.cs +++ b/src/Weather.API/Features/GetFavorites/FavoritesWeatherDto.cs @@ -1,9 +1,9 @@ -using Weather.API.Domain.Dtos; +using Weather.API.Features.GetFavorites; namespace Weather.API.Features.Favorites.GetFavorites { public sealed class FavoritesWeatherDto { - public IReadOnlyCollection FavoriteWeathers { get; init; } = new List(); + public IReadOnlyCollection FavoriteWeathers { get; init; } = new List(); } } diff --git a/src/Weather.API/Features/GetFavorites/GetFavoritesHandler.cs b/src/Weather.API/Features/GetFavorites/GetFavoritesHandler.cs index c042b64..9585338 100644 --- a/src/Weather.API/Features/GetFavorites/GetFavoritesHandler.cs +++ b/src/Weather.API/Features/GetFavorites/GetFavoritesHandler.cs @@ -5,10 +5,12 @@ using Validot; using Weather.API.Domain.Abstractions; using Weather.API.Domain.Database.EFContext; +using Weather.API.Domain.Database.Entities; using Weather.API.Domain.Dtos; using Weather.API.Domain.Extensions; using Weather.API.Domain.Logging; using Weather.API.Domain.Resources; +using Weather.API.Features.GetFavorites; using WeatherApi.Domain.Http; namespace Weather.API.Features.Favorites.GetFavorites @@ -40,7 +42,7 @@ public GetFavoritesHandler( public async Task> HandleAsync(EmptyRequest request, CancellationToken cancellationToken) { - var favoriteLocations = await GetFavoritesAync(cancellationToken); + var favoriteLocations = await _weatherContext.FavoriteLocations.ToListAsync(cancellationToken); if (!favoriteLocations.HasAny()) { @@ -51,14 +53,14 @@ public async Task> HandleAsync(EmptyReques } - private async Task> GetFavoritesAsync(IEnumerable favoriteLocationsResult, CancellationToken cancellationToken) + private async Task> GetFavoritesAsync(IEnumerable favoriteLocationsResult, CancellationToken cancellationToken) { - var result = new List(); + var result = new List(); var errorMessages = new List(); await favoriteLocationsResult.ForEachAsync(async (location) => { - var favoriteWeather = await GetWeatherAsync(location, cancellationToken); + var favoriteWeather = await GetWeatherAsync(_mapper.Map(location), cancellationToken); if (favoriteWeather.IsFailed) { @@ -66,7 +68,15 @@ await favoriteLocationsResult.ForEachAsync(async (location) => return; } - result.Add(favoriteWeather.Value); + result.Add(new FavoriteCurrentWeatherDto + { + CityName = favoriteWeather.Value.CityName, + DateTime = favoriteWeather.Value.DateTime, + Sunrise = favoriteWeather.Value.Sunrise, + Sunset = favoriteWeather.Value.Sunset, + Id = location.Id, + Temperature = favoriteWeather.Value.Temperature + }); }); return result.Any() ? diff --git a/src/Weather.API/Program.cs b/src/Weather.API/Program.cs index 90f7d2e..ef48b6d 100644 --- a/src/Weather.API/Program.cs +++ b/src/Weather.API/Program.cs @@ -1,5 +1,6 @@ using Weather.API.Configuration; using Weather.API.Features.AddFavorites; +using Weather.API.Features.DeleteFavorites; using Weather.API.Features.Favorites.AddFavorites; using Weather.API.Features.Favorites.GetFavorites; using Weather.API.Features.GetFavorites; @@ -14,7 +15,8 @@ .AddAddFavorites() .AddGetFavorites() .AddGetCurrentWeather() - .AddGetForecastWeather(); + .AddGetForecastWeather() + .AddDeleteFavorites(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); @@ -36,6 +38,7 @@ .BuildAddFavoriteWeatherEndpoints() .BuildGetFavoriteWeatherEndpoints() .BuildGetForecastWeatherEndpoints() - .BuildGetCurrentWeatherEndpoints(); + .BuildGetCurrentWeatherEndpoints() + .BuildDeleteFavoriteWeatherEndpoints(); app.Run(); \ No newline at end of file From 35c1d6cd5c157577a6d3382bdbcf50ffa95a9357 Mon Sep 17 00:00:00 2001 From: Gramli Date: Wed, 6 Mar 2024 09:00:20 +0100 Subject: [PATCH 2/3] add and fix unit tests --- .../AddFavorites/AddFavoriteHandlerTests.cs | 7 +- .../DeleteFavoriteHandlerTests.cs | 94 +++++++++++++++++++ .../GetFavorites/GetFavoritesHandlerTests.cs | 18 ++-- .../DeleteFavorites/DeleteFavoriteHandler.cs | 5 +- 4 files changed, 105 insertions(+), 19 deletions(-) create mode 100644 src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs diff --git a/src/Tests/Weather.API.UnitTests/Features/AddFavorites/AddFavoriteHandlerTests.cs b/src/Tests/Weather.API.UnitTests/Features/AddFavorites/AddFavoriteHandlerTests.cs index 536575e..95f5ef8 100644 --- a/src/Tests/Weather.API.UnitTests/Features/AddFavorites/AddFavoriteHandlerTests.cs +++ b/src/Tests/Weather.API.UnitTests/Features/AddFavorites/AddFavoriteHandlerTests.cs @@ -22,14 +22,14 @@ public class AddFavoriteHandlerTests private readonly Mock _mapperMock; private readonly Mock> _favoriteLocationEntityDbSetMock; - private readonly IRequestHandler _uut; + private readonly IRequestHandler _uut; public AddFavoriteHandlerTests() { _favoriteLocationEntityDbSetMock = new(); _weatherContextMock = new(); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); - _addFavoriteCommandValidatorMock = new Mock>(); + _addFavoriteCommandValidatorMock = new(); _loggerMock = new(); _mapperMock = new(); @@ -51,7 +51,6 @@ public async Task InvalidLocation() //Assert Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); Assert.Single(result.Errors); - Assert.False(result.Data); _addFavoriteCommandValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(addFavoriteCommand))), Times.Once); } @@ -72,7 +71,6 @@ public async Task AddFavoriteLocation_Failed() //Assert Assert.Equal(HttpStatusCode.InternalServerError, result.StatusCode); Assert.Single(result.Errors); - Assert.False(result.Data); _addFavoriteCommandValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(addFavoriteCommand))), Times.Once); _loggerMock.VerifyLog(LogLevel.Error, LogEvents.FavoriteWeathersStoreToDatabase, Times.Once()); } @@ -96,7 +94,6 @@ public async Task Success() //Assert Assert.Equal(HttpStatusCode.OK, result.StatusCode); Assert.Empty(result.Errors); - Assert.True(result.Data); _addFavoriteCommandValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(addFavoriteCommand))), Times.Once); _favoriteLocationEntityDbSetMock.Verify(x => x.AddAsync(It.IsAny(), It.IsAny()), Times.Once); } diff --git a/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs b/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs new file mode 100644 index 0000000..9d342ff --- /dev/null +++ b/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs @@ -0,0 +1,94 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Moq; +using System.Net; +using Validot; +using Weather.API.Domain.Abstractions; +using Weather.API.Domain.Database.Entities; +using Weather.API.Domain.Dtos; +using Weather.API.Features.DeleteFavorites; +using Weather.API.UnitTests.Domain.Database; + + +namespace Weather.API.UnitTests.Features.DeleteFavorites +{ + public class DeleteFavoriteHandlerTests + { + private readonly Mock> _deleteFavoriteCommandValidatorMock; + private readonly Mock> _loggerMock; + private readonly Mock _weatherContextMock; + private readonly Mock> _favoriteLocationEntityDbSetMock; + + private readonly IRequestHandler _uut; + public DeleteFavoriteHandlerTests() + { + _deleteFavoriteCommandValidatorMock = new(); + _loggerMock = new(); + _weatherContextMock = new(); + _favoriteLocationEntityDbSetMock = new(); + + _uut = new DeleteFavoriteHandler(_deleteFavoriteCommandValidatorMock.Object, _loggerMock.Object, _weatherContextMock.Object); + } + + [Fact] + public async Task InvalidRequest() + { + //Arrange + var deleteFavoriteCommand = new DeleteFavoriteCommand { Id = 1 }; + + _deleteFavoriteCommandValidatorMock.Setup(x => x.IsValid(deleteFavoriteCommand)).Returns(false); + + //Act + var result = await _uut.HandleAsync(deleteFavoriteCommand, CancellationToken.None); + + //Assert + Assert.Equal(HttpStatusCode.BadRequest, result.StatusCode); + Assert.Single(result.Errors); + Assert.False(result.Data); + } + + [Fact] + public async Task DeleteFavoriteLocationSafeAsync_Failed() + { + //Arrange + var deleteFavoriteCommand = new DeleteFavoriteCommand { Id = 1 }; + + _deleteFavoriteCommandValidatorMock.Setup(x => x.IsValid(deleteFavoriteCommand)).Returns(true); + + var favoriteLocation = new FavoriteLocationEntity(); + _favoriteLocationEntityDbSetMock.Setup(x => x.FindAsync(It.IsAny(), CancellationToken.None)).ThrowsAsync(new DbUpdateException()); + _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); + + //Act + var result = await _uut.HandleAsync(deleteFavoriteCommand, CancellationToken.None); + + //Assert + Assert.Equal(HttpStatusCode.InternalServerError, result.StatusCode); + Assert.Single(result.Errors); + Assert.False(result.Data); + } + + [Fact] + public async Task Success() + { + //Arrange + var deleteFavoriteCommand = new DeleteFavoriteCommand { Id = 1 }; + + _deleteFavoriteCommandValidatorMock.Setup(x => x.IsValid(deleteFavoriteCommand)).Returns(true); + + var favoriteLocation = new FavoriteLocationEntity(); + _favoriteLocationEntityDbSetMock.Setup(x => x.FindAsync(It.IsAny(), CancellationToken.None)).ReturnsAsync(favoriteLocation); + _favoriteLocationEntityDbSetMock.Setup(x => x.Remove(favoriteLocation)); + _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); + + //Act + var result = await _uut.HandleAsync(deleteFavoriteCommand, CancellationToken.None); + + //Assert + Assert.Equal(HttpStatusCode.OK, result.StatusCode); + Assert.Empty(result.Errors); + Assert.True(result.Data); + } + + } +} diff --git a/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs b/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs index 3d37c29..9e6f77b 100644 --- a/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs +++ b/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs @@ -35,7 +35,6 @@ public GetFavoritesHandlerTests() _currentWeatherValidatorMock = new(); _weatherContextMock = new(); _mapperMock = new(); - _favoriteLocationEntityDbSetMock = new(); _uut = new GetFavoritesHandler( @@ -94,11 +93,10 @@ public async Task EmptyResult_GetCurrentWeather_Fail() var favoriteLocations = new List() { new() }; _favoriteLocationEntityDbSetMock.SetupMock(favoriteLocations); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); - _mapperMock.Setup(x => x.Map>(favoriteLocations)).Returns(new List { locationDto }); - + _mapperMock.Setup(x => x.Map(It.IsAny())).Returns(locationDto); _locationValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(true); - _weatherServiceMock.Setup(x => x.GetCurrentWeather(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Fail(failMessage)); + //Act var result = await _uut.HandleAsync(EmptyRequest.Instance, CancellationToken.None); @@ -117,11 +115,11 @@ public async Task One_Of_GetCurrentWeather_Failed() var failMessage = "Some fail message"; var locationDto = new LocationDto { Latitude = 1, Longitude = 1 }; - var favoriteLocations = new List() { new() }; + var favoriteLocations = new List() { new(), new FavoriteLocationEntity { Latitude = locationDto.Latitude, Longitude = locationDto.Longitude } }; _favoriteLocationEntityDbSetMock.SetupMock(favoriteLocations); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); - _mapperMock.Setup(x => x.Map>(favoriteLocations)).Returns(new List { locationDto, new() }); - + _mapperMock.Setup(x => x.Map(It.Is(y=> y.Latitude!= locationDto.Latitude))).Returns(new LocationDto()); + _mapperMock.Setup(x => x.Map(It.Is(y => y.Latitude == locationDto.Latitude))).Returns(locationDto); _locationValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(true); var currentWeather = new CurrentWeatherDto(); @@ -138,7 +136,6 @@ public async Task One_Of_GetCurrentWeather_Failed() Assert.Single(result.Errors); Assert.NotNull(result.Data); Assert.Single(result.Data.FavoriteWeathers); - Assert.Equal(currentWeather, result.Data.FavoriteWeathers.Single()); _weatherServiceMock.Verify(x => x.GetCurrentWeather(It.IsAny(), It.IsAny()), Times.Exactly(2)); _loggerMock.VerifyLog(LogLevel.Warning, LogEvents.FavoriteWeathersGeneral, failMessage, Times.Once()); _locationValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(locationDto))), Times.Once); @@ -154,7 +151,7 @@ public async Task GetCurrentWeather_Validation_Fail() var favoriteLocations = new List() { new() }; _favoriteLocationEntityDbSetMock.SetupMock(favoriteLocations); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); - _mapperMock.Setup(x => x.Map>(favoriteLocations)).Returns(new List { locationDto }); + _mapperMock.Setup(x => x.Map(It.IsAny())).Returns(locationDto); _locationValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(true); _currentWeatherValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(false); @@ -182,7 +179,7 @@ public async Task Success() var favoriteLocations = new List() { new() }; _favoriteLocationEntityDbSetMock.SetupMock(favoriteLocations); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); - _mapperMock.Setup(x => x.Map>(favoriteLocations)).Returns(new List { locationDto }); + _mapperMock.Setup(x => x.Map(It.IsAny())).Returns(locationDto); _locationValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(true); _currentWeatherValidatorMock.Setup(x => x.IsValid(It.IsAny())).Returns(true); @@ -197,7 +194,6 @@ public async Task Success() Assert.Empty(result.Errors); Assert.NotNull(result.Data); Assert.Single(result.Data.FavoriteWeathers); - Assert.Equal(currentWeather, result.Data.FavoriteWeathers.Single()); _weatherServiceMock.Verify(x => x.GetCurrentWeather(It.Is(y => y.Equals(locationDto)), It.IsAny()), Times.Once); _locationValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(locationDto))), Times.Once); _currentWeatherValidatorMock.Verify(x => x.IsValid(It.Is(y => y.Equals(currentWeather))), Times.Once); diff --git a/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs index 27f1e4d..37854e9 100644 --- a/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs +++ b/src/Weather.API/Features/DeleteFavorites/DeleteFavoriteHandler.cs @@ -7,7 +7,6 @@ using Weather.API.Domain.Extensions; using Weather.API.Domain.Logging; using Weather.API.Domain.Resources; -using Weather.API.Features.Favorites.AddFavorites; using WeatherApi.Domain.Http; namespace Weather.API.Features.DeleteFavorites @@ -16,10 +15,10 @@ internal sealed class DeleteFavoriteHandler : IRequestHandler _validator; - private readonly ILogger _logger; + private readonly ILogger _logger; public DeleteFavoriteHandler( IValidator validator, - ILogger logger, + ILogger logger, WeatherContext weatherContext) { _validator = Guard.Against.Null(validator); From f783c748a8cab8c9c52aff8597be6c04280a98dd Mon Sep 17 00:00:00 2001 From: Gramli Date: Wed, 6 Mar 2024 09:48:45 +0100 Subject: [PATCH 3/3] fix codacy issues --- .../Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs | 7 ++----- .../Features/GetFavorites/GetFavoritesHandlerTests.cs | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs b/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs index 9d342ff..c375773 100644 --- a/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs +++ b/src/Tests/Weather.API.UnitTests/Features/DeleteFavorites/DeleteFavoriteHandlerTests.cs @@ -5,7 +5,6 @@ using Validot; using Weather.API.Domain.Abstractions; using Weather.API.Domain.Database.Entities; -using Weather.API.Domain.Dtos; using Weather.API.Features.DeleteFavorites; using Weather.API.UnitTests.Domain.Database; @@ -15,7 +14,6 @@ namespace Weather.API.UnitTests.Features.DeleteFavorites public class DeleteFavoriteHandlerTests { private readonly Mock> _deleteFavoriteCommandValidatorMock; - private readonly Mock> _loggerMock; private readonly Mock _weatherContextMock; private readonly Mock> _favoriteLocationEntityDbSetMock; @@ -23,11 +21,11 @@ public class DeleteFavoriteHandlerTests public DeleteFavoriteHandlerTests() { _deleteFavoriteCommandValidatorMock = new(); - _loggerMock = new(); + var loggerMock = new Mock>(); _weatherContextMock = new(); _favoriteLocationEntityDbSetMock = new(); - _uut = new DeleteFavoriteHandler(_deleteFavoriteCommandValidatorMock.Object, _loggerMock.Object, _weatherContextMock.Object); + _uut = new DeleteFavoriteHandler(_deleteFavoriteCommandValidatorMock.Object, loggerMock.Object, _weatherContextMock.Object); } [Fact] @@ -55,7 +53,6 @@ public async Task DeleteFavoriteLocationSafeAsync_Failed() _deleteFavoriteCommandValidatorMock.Setup(x => x.IsValid(deleteFavoriteCommand)).Returns(true); - var favoriteLocation = new FavoriteLocationEntity(); _favoriteLocationEntityDbSetMock.Setup(x => x.FindAsync(It.IsAny(), CancellationToken.None)).ThrowsAsync(new DbUpdateException()); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); diff --git a/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs b/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs index 9e6f77b..adb0069 100644 --- a/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs +++ b/src/Tests/Weather.API.UnitTests/Features/GetFavorites/GetFavoritesHandlerTests.cs @@ -115,7 +115,7 @@ public async Task One_Of_GetCurrentWeather_Failed() var failMessage = "Some fail message"; var locationDto = new LocationDto { Latitude = 1, Longitude = 1 }; - var favoriteLocations = new List() { new(), new FavoriteLocationEntity { Latitude = locationDto.Latitude, Longitude = locationDto.Longitude } }; + var favoriteLocations = new List { new(), new FavoriteLocationEntity { Latitude = locationDto.Latitude, Longitude = locationDto.Longitude } }; _favoriteLocationEntityDbSetMock.SetupMock(favoriteLocations); _weatherContextMock.Setup(x => x.FavoriteLocations).Returns(_favoriteLocationEntityDbSetMock.Object); _mapperMock.Setup(x => x.Map(It.Is(y=> y.Latitude!= locationDto.Latitude))).Returns(new LocationDto());