Валидация вставки / обновления + интеграционные тесты (начало)

This commit is contained in:
Olga Nemt 2024-01-25 10:35:16 +05:00
parent f9504aea21
commit 011a479a4b
5 changed files with 173 additions and 41 deletions

View File

@ -2,6 +2,7 @@
using AsbCloudApp.Requests;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using System.Threading.Tasks;
@ -120,7 +121,7 @@ namespace AsbCloudApp.Repositories
/// </summary>
/// <param name="wellOperations"></param>
/// <returns></returns>
bool Validate(IEnumerable<WellOperationDto> wellOperations);
IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperations);
/// <summary>
/// Валидация данных (проверка с базой)
@ -128,6 +129,6 @@ namespace AsbCloudApp.Repositories
/// <param name="wellOperations"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
}
}

View File

@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -333,12 +334,12 @@ public class WellOperationRepository : IWellOperationRepository
return dtos;
}
public async Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
public IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
{
var firstOperation = wellOperationDtos
.FirstOrDefault();
if (firstOperation is null)
return false;
return Enumerable.Empty<ValidationResult>();
var request = new WellOperationRequest()
{
@ -346,53 +347,51 @@ public class WellOperationRepository : IWellOperationRepository
OperationType = firstOperation.IdType,
};
var entities = await BuildQuery(request)
var entities = BuildQuery(request)
.AsNoTracking()
.ToArrayAsync(token)
.ConfigureAwait(false);
.ToArray();
if (!entities.Any())
return Validate(wellOperationDtos);
var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart);
var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart).ToArray();
return Validate(wellOperationsUnion);
}
for(var i = 1; i < wellOperationsUnion.Count(); i++)
public IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperationDtos)
{
var firstOperation = wellOperationDtos
.FirstOrDefault();
if (firstOperation is null)
return Enumerable.Empty<ValidationResult>();
var validationResults = new List<ValidationResult>();
var wellOperations = wellOperationDtos.ToArray();
for (var i = wellOperations.Count() - 1; i >= 1; i--)
{
var prevOperation = wellOperationsUnion[i - 1];
var currentOperation = wellOperationsUnion[i];
var prevOperation = wellOperations[i - 1];
var currentOperation = wellOperations[i];
var prevOperationDateStart = prevOperation.DateStart.ToUniversalTime();
var currentOperationDateStart = currentOperation.DateStart.ToUniversalTime();
var prevOperationDateEnd = prevOperation.DateStart.AddHours(prevOperation.DurationHours).ToUniversalTime();
var currrentOperationDateEnd = currentOperation.DateStart.AddHours(currentOperation.DurationHours).ToUniversalTime();
if (currentOperation.Id == 0 && ((prevOperationDateStart.AddDays(Gap) < currentOperationDateStart) || (prevOperationDateEnd >= currrentOperationDateEnd)))
if (prevOperationDateStart.AddDays(Gap) < currentOperationDateStart)
{
return false;
validationResults.Add(new ValidationResult(
$"Разница дат между операциями не должна превышать 90 дней",
new[] { nameof(wellOperations) }));
}
if (prevOperationDateEnd > currentOperationDateStart)
{
validationResults.Add(new ValidationResult(
$"Предыдущая операция не завершена",
new[] { nameof(wellOperations) }));
}
}
return true;
}
public bool Validate(IEnumerable<WellOperationDto> wellOperationDtos)
{
var firstOperation = wellOperationDtos
.FirstOrDefault();
if (firstOperation is null)
return false;
var maxOperationDateStart = firstOperation.DateStart.ToUniversalTime();
foreach (var dto in wellOperationDtos)
{
var currentOperationDateStart = dto.DateStart.ToUniversalTime();
if (maxOperationDateStart.AddDays(Gap) < currentOperationDateStart)
return false;
maxOperationDateStart = currentOperationDateStart;
}
return true;
return validationResults;
}
/// <inheritdoc/>

View File

@ -0,0 +1,14 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMapPlan;
using AsbCloudApp.Requests;
using Refit;
namespace AsbCloudWebApi.IntegrationTests.Clients;
public interface IWellOperationClient
{
private const string BaseRoute = "/api/wellOperation";
[Post(BaseRoute)]
Task<IApiResponse<int>> InsertRange(int idWell, [Body] IEnumerable<WellOperationDto> dtos);
}

View File

@ -0,0 +1,115 @@
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMapPlan;
using AsbCloudApp.Requests;
using AsbCloudDb.Model;
using AsbCloudDb.Model.ProcessMaps;
using AsbCloudWebApi.IntegrationTests.Clients;
using System.Net;
using Xunit;
namespace AsbCloudWebApi.IntegrationTests.Controllers;
public class WellOperationControllerTest : BaseIntegrationTest
{
private readonly int idWell = 4;
private readonly WellOperationDto[] dtos = new WellOperationDto[]
{
new WellOperationDto()
{
},
new WellOperationDto()
{
}
};
private IWellOperationClient wellOperationClient;
public WellOperationControllerTest(WebAppFactoryFixture factory)
: base(factory)
{
wellOperationClient = factory.GetAuthorizedHttpClient<IWellOperationClient>();
var rep = factory.Get
}
/// <summary>
/// Успешное добавление операции с предварительной очисткой
/// </summary>
/// <returns></returns>
[Fact]
public async Task InsertRangeWithDeleteBefore_returns_success()
{
////arrange
//dbContext.WellOperations.Add(wellOperation);
//dbContext.SaveChanges();
//var request = new OperationStatRequest
//{
// DateStartUTC = schedule.DrillStart.DateTime,
// DateEndUTC = schedule.DrillEnd.DateTime,
// DurationMinutesMin = 0,
// DurationMinutesMax = 5
//};
//var dtoExpected = new SlipsStatDto
//{
// DrillerName = $"{Data.Defaults.Drillers[0].Surname} {Data.Defaults.Drillers[0].Name} {Data.Defaults.Drillers[0].Patronymic}",
// WellCount = 1,
// SectionCaption = "Пилотный ствол",
// SlipsCount = 1,
// SlipsTimeInMinutes = (detectedOperation.DateEnd - detectedOperation.DateStart).TotalMinutes,
// SectionDepth = factWellOperation.DepthEnd - factWellOperation.DepthStart,
//};
////act
//var response = await slipsTimeClient.GetAll(request);
////assert
//Assert.NotNull(response.Content);
//Assert.Single(response.Content);
//var dtoActual = response.Content.First();
//MatchHelper.Match(dtoExpected, dtoActual);
}
/// <summary>
/// Успешное добавление операции без очистки
/// </summary>
/// <returns></returns>
[Fact]
public async Task InsertRange_returns_success() {
//arrange
var dbset = dbContext.Set<WellOperation>();
dbset.RemoveRange(dbset);
dbContext.SaveChanges();
operationRepository.Validate(dtos);
//act
var response = await wellOperationClient.InsertRange(idWell, dtos);
//assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}
/// <summary>
/// Неуспешное добавление операции с предварительной очисткой
/// </summary>
/// <returns></returns>
[Fact]
public async Task InsertRangeWithDeleteBefore_returns_error()
{
}
/// <summary>
/// Неуспешное добавление операции без очистки
/// </summary>
/// <returns></returns>
[Fact]
public async Task InsertRange_returns_error()
{
}
}

View File

@ -237,7 +237,8 @@ namespace AsbCloudWebApi.Controllers
wellOperation.IdUser = User.GetUserId();
wellOperation.IdType = idType;
if (!await operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken))
var validationResult = operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken);
if(validationResult.Any())
return this.ValidationBadRequest(nameof(wellOperation), "The date difference between the operations is more than 3 months");
var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken);
@ -291,7 +292,8 @@ namespace AsbCloudWebApi.Controllers
}
if (!await Validate(wellOperations, deleteBeforeInsert, cancellationToken))
var validationResult = Validate(wellOperations, deleteBeforeInsert, cancellationToken);
if (validationResult.Any())
return this.ValidationBadRequest(nameof(wellOperations), "The date difference between the operations is more than 3 months");
var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken);
@ -307,12 +309,12 @@ namespace AsbCloudWebApi.Controllers
/// <param name="deleteBeforeInsert"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<bool> Validate(IEnumerable<WellOperationDto> wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
private IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
{
if (deleteBeforeInsert)
return operationRepository.Validate(wellOperations);
else
return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
return operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
}
/// <summary>
@ -340,7 +342,8 @@ namespace AsbCloudWebApi.Controllers
value.LastUpdateDate = DateTimeOffset.UtcNow;
value.IdUser = User.GetUserId();
if (!await operationRepository.ValidateWithDbAsync(new[] { value }, token))
var validationResult = operationRepository.ValidateWithDbAsync(new[] { value }, token);
if (validationResult.Any())
return this.ValidationBadRequest(nameof(value), "The date difference between the operations is more than 3 months");
var result = await operationRepository.UpdateAsync(value, token)