From 6e34f5f4c6a692412e882601e23d2b07b16f94d0 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Thu, 18 Apr 2024 10:06:46 +0500 Subject: [PATCH 1/3] =?UTF-8?q?=D0=94=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D1=8B=20=D0=B0=D0=B2=D1=82=D0=BE=D1=82=D0=B5=D1=81=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WellCompositeOperationServiceTest.cs | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs index 14224abd..271e9c7e 100644 --- a/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs +++ b/AsbCloudWebApi.Tests/Services/WellCompositeOperation/WellCompositeOperationServiceTest.cs @@ -26,9 +26,7 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation = Substitute.For(); private IWellService wellService = Substitute.For(); - - - + private List idsWells; private readonly static IEnumerable operationCategories = new List() { new(){Id = 5096, Name = "Шаблонирование перед спуском"}, @@ -47,6 +45,12 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation new() {Id = 31, Caption = "Техническая колонна", Order = 2} }; + private readonly static IEnumerable wells = new List() + { + new() {Id = 55, Caption = "Скважина с ключом 55"}, + new() {Id = 64, Caption = "Скважина с ключом 64"}, + }; + private readonly static IEnumerable wellOperations1 = new List() { new() @@ -162,6 +166,11 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationCategoryRepository.Get(Arg.Any()) .Returns(operationCategories); + idsWells = new List() { 55, 64 }; + + wellService.GetAsync(Arg.Any(), Arg.Any()) + .Returns(wells); + service = new WellCompositeOperationService( wellSectionTypeRepository, wellOperationCategoryRepository, @@ -182,10 +191,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations1); - var idsWell = new List() { 55, 64 }; - // act - var result = await service.GetAsync(idsWell, CancellationToken.None); + var result = await service.GetAsync(idsWells, CancellationToken.None); // assert var compositeWellOperations = result.WellOperationsComposite; @@ -211,10 +218,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations2); - var idsWell = new List() { 55, 64 }; - // act - var result = await service.GetAsync(idsWell, CancellationToken.None); + var result = await service.GetAsync(idsWells, CancellationToken.None); // assert var compositeWellOperations = result.WellOperationsComposite; @@ -237,10 +242,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations3); - var idsWell = new List() { 55, 64 }; - // act - var result = await service.GetAsync(idsWell, CancellationToken.None); + var result = await service.GetAsync(idsWells, CancellationToken.None); // assert var compositeWellOperations = result.WellOperationsComposite; @@ -265,10 +268,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations4); - var idsWell = new List() { 55, 64 }; - // act - var result = await service.GetAsync(idsWell, CancellationToken.None); + var result = await service.GetAsync(idsWells, CancellationToken.None); // assert var compositeWellOperations = result.WellOperationsComposite; @@ -297,10 +298,8 @@ namespace AsbCloudWebApi.Tests.Services.WellCompositeOperation wellOperationRepository.GetAsync(Arg.Any(), Arg.Any()) .Returns(wellOperations); - var idsWell = new List() { 55, 64 }; - // act - var result = await service.GetAsync(idsWell, CancellationToken.None); + var result = await service.GetAsync(idsWells, CancellationToken.None); // assert var wellOperationsCount = result.WellCompositeSourceOperations From f18886639123574a3b8a9ac399c3d32bb9879590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 18 Apr 2024 09:40:43 +0300 Subject: [PATCH 2/3] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=83=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=D0=BE=D0=BA=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=BD=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AsbCloudInfrastructure/DependencyInjection.cs | 5 +++++ AsbCloudInfrastructure/Repository/CacheBase.cs | 2 +- .../Repository/SetpointsRequestRepository.cs | 5 +++++ AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs | 6 ++---- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 6e8b3e89..713f5614 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -52,6 +52,11 @@ namespace AsbCloudInfrastructure { public static void MapsterSetup() { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(source => source.Author) + .Ignore(source => source.Well); + TypeAdapterConfig.GlobalSettings.Default.Config .ForType() .Ignore(source => source.OperationCategory); diff --git a/AsbCloudInfrastructure/Repository/CacheBase.cs b/AsbCloudInfrastructure/Repository/CacheBase.cs index 28d07f07..84f702df 100644 --- a/AsbCloudInfrastructure/Repository/CacheBase.cs +++ b/AsbCloudInfrastructure/Repository/CacheBase.cs @@ -53,7 +53,7 @@ namespace AsbCloudInfrastructure.Repository cacheEntry.AbsoluteExpirationRelativeToNow = CacheObsolescence; cacheEntry.SlidingExpiration = CacheObsolescence; - var entities = await this.GetQuery().ToArrayAsync(token); + var entities = await GetQuery().AsNoTracking().ToArrayAsync(token); cacheEntry.Value = entities; return entities.AsEnumerable(); }); diff --git a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs index 2c1f7905..c2b359db 100644 --- a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs +++ b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs @@ -40,9 +40,14 @@ namespace AsbCloudInfrastructure.Repository { var entity = Convert(dto); var entry = dbSet.Update(entity); + entry.State = EntityState.Detached; } var affected = await dbContext.SaveChangesAsync(token); + + if(affected > 0) + DropCache(); + return affected; } diff --git a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs index d06e0b4c..383c587f 100644 --- a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs @@ -2,7 +2,6 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; @@ -62,9 +61,8 @@ namespace AsbCloudInfrastructure.Services.SAUB var all = await setpointsRepository.GetAllAsync(token); var filtered = all.Where(s => s.IdWell == idWell && - s.IdState == 1 && - s.UploadDate.AddSeconds(s.ObsolescenceSec) > DateTime.UtcNow) - .ToList(); + s.IdState == 1 && + s.UploadDate.AddSeconds(s.ObsolescenceSec) > DateTime.UtcNow); if (!filtered.Any()) return Enumerable.Empty(); From 60091b36cb97ebc7f5759614183a2065f4a1a3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 18 Apr 2024 13:53:05 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B.=20=D0=9D=D0=B5?= =?UTF-8?q?=D0=B1=D0=BE=D0=BB=D1=8C=D1=88=D0=BE=D0=B9=20=D1=80=D0=B5=D1=84?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/SetpointsRequestRepository.cs | 42 +++++++++------ .../Services/SAUB/SetpointsService.cs | 5 +- .../Clients/ISetpointsClient.cs | 12 +++++ .../Controllers/SetpointsControllerTest.cs | 53 +++++++++++++++++++ 4 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 AsbCloudWebApi.IntegrationTests/Clients/ISetpointsClient.cs create mode 100644 AsbCloudWebApi.IntegrationTests/Controllers/SetpointsControllerTest.cs diff --git a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs index c2b359db..2a728bd5 100644 --- a/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs +++ b/AsbCloudInfrastructure/Repository/SetpointsRequestRepository.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using System.Threading; using System.Linq; +using AsbCloudApp.Exceptions; namespace AsbCloudInfrastructure.Repository { @@ -23,28 +24,37 @@ namespace AsbCloudInfrastructure.Repository this.wellService = wellService; } + //TODO: заметка для рефакторинга. Использовать метод из базового репозитория public virtual async Task UpdateRangeAsync(IEnumerable dtos, CancellationToken token) { - var ids = dtos.Select(d => d.Id); - var existingEntities = await dbSet - .AsNoTracking() - .Where(d => ids.Contains(d.Id)) - .Select(d => d.Id) - .ToListAsync(token) - .ConfigureAwait(false); + if (!dtos.Any()) + return 0; + + var ids = dtos + .Select(o => o.Id) + .Distinct() + .ToArray(); + + if (ids.Any(id => id == default)) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь Id"); + + if (ids.Length != dtos.Count()) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны иметь уникальные Id"); + + var existingEntitiesCount = await dbContext.Set() + .Where(o => ids.Contains(o.Id)) + .CountAsync(token); + + if (ids.Length != existingEntitiesCount) + throw new ArgumentInvalidException(nameof(dtos), "Все записи должны существовать в БД"); - if (ids.Count() > existingEntities.Count) - return ICrudRepository.ErrorIdNotFound; - - foreach (var dto in dtos) - { - var entity = Convert(dto); - var entry = dbSet.Update(entity); - entry.State = EntityState.Detached; - } + var entities = dtos.Select(Convert); + var entries = entities.Select(entity => dbContext.Set().Update(entity)).ToList(); var affected = await dbContext.SaveChangesAsync(token); + entries.ForEach(entry => entry.State = EntityState.Detached); + if(affected > 0) DropCache(); diff --git a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs index 383c587f..e68eeef3 100644 --- a/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs +++ b/AsbCloudInfrastructure/Services/SAUB/SetpointsService.cs @@ -62,15 +62,14 @@ namespace AsbCloudInfrastructure.Services.SAUB var filtered = all.Where(s => s.IdWell == idWell && s.IdState == 1 && - s.UploadDate.AddSeconds(s.ObsolescenceSec) > DateTime.UtcNow); + s.UploadDate.AddSeconds(s.ObsolescenceSec).UtcDateTime > DateTime.UtcNow) + .ToArray(); if (!filtered.Any()) return Enumerable.Empty(); foreach (var item in filtered) - { item.IdState = 2; - } await setpointsRepository.UpdateRangeAsync(filtered, token); diff --git a/AsbCloudWebApi.IntegrationTests/Clients/ISetpointsClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/ISetpointsClient.cs new file mode 100644 index 00000000..c8e6e523 --- /dev/null +++ b/AsbCloudWebApi.IntegrationTests/Clients/ISetpointsClient.cs @@ -0,0 +1,12 @@ +using AsbCloudApp.Data.SAUB; +using Refit; + +namespace AsbCloudWebApi.IntegrationTests.Clients; + +public interface ISetpointsClient +{ + private const string BaseRoute = "/api/telemetry/{uid}/Setpoints"; + + [Get(BaseRoute)] + Task>> GetByTelemetryUidAsync(string uid); +} \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/SetpointsControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/SetpointsControllerTest.cs new file mode 100644 index 00000000..d73148de --- /dev/null +++ b/AsbCloudWebApi.IntegrationTests/Controllers/SetpointsControllerTest.cs @@ -0,0 +1,53 @@ +using System.Net; +using AsbCloudDb.Model; +using AsbCloudWebApi.IntegrationTests.Clients; +using Microsoft.EntityFrameworkCore; +using Xunit; + +namespace AsbCloudWebApi.IntegrationTests.Controllers; + +public class SetpointsControllerTest : BaseIntegrationTest +{ + private readonly ISetpointsClient client; + + public SetpointsControllerTest(WebAppFactoryFixture factory) + : base(factory) + { + client = factory.GetAuthorizedHttpClient(string.Empty); + } + + [Fact] + public async Task GetByTelemetryUidAsync_returns_success() + { + //arrange + var well = await dbContext.Wells + .Include(w => w.Telemetry) + .FirstAsync(); + + var entity = new SetpointsRequest + { + IdWell = well.Id, + UploadDate = DateTimeOffset.UtcNow, + ObsolescenceSec = 15, + IdState = 1, + IdAuthor = 1 + }; + + var entry = dbContext.SetpointsRequests.Add(entity); + await dbContext.SaveChangesAsync(); + entry.State = EntityState.Detached; + + //act + var response = await client.GetByTelemetryUidAsync(well.Telemetry!.RemoteUid); + + //assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(response.Content); + Assert.Single(response.Content); + + var setpoints = await dbContext.SetpointsRequests.ToArrayAsync(); + + foreach (var setpoint in setpoints) + Assert.Equal(2, setpoint.IdState); + } +} \ No newline at end of file