persistence/DD.Persistence.IntegrationTests/Controllers/ChangeLogControllerTest.cs

404 lines
15 KiB
C#
Raw Normal View History

using DD.Persistence.Client;
using DD.Persistence.Client.Clients;
using DD.Persistence.Client.Clients.Interfaces;
using DD.Persistence.Client.Clients.Interfaces.Refit;
using DD.Persistence.Database.Entity;
using DD.Persistence.Models;
using DD.Persistence.Models.Requests;
using DD.Persistence.Models.Requests.ChangeLog;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using UuidExtensions;
using Xunit;
namespace DD.Persistence.IntegrationTests.Controllers;
public class ChangeLogControllerTest : BaseIntegrationTest
{
private readonly IChangeLogClient client;
private readonly PaginationRequest paginationRequest;
private static readonly Random generatorRandomDigits = new();
public ChangeLogControllerTest(WebAppFactoryFixture factory) : base(factory)
{
var refitClientFactory = scope.ServiceProvider
.GetRequiredService<IRefitClientFactory<IRefitChangeLogClient>>();
var logger = scope.ServiceProvider.GetRequiredService<ILogger<ChangeLogClient>>();
client = scope.ServiceProvider
.GetRequiredService<IChangeLogClient>();
paginationRequest = new PaginationRequest()
{
Skip = 0,
Take = 10,
SortSettings = String.Empty,
};
}
[Fact]
public async Task ClearAndInsertRange_InNotEmptyDb()
{
// arrange
var insertedCount = 10;
var newEntitiesData = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
var idDiscriminator = newEntitiesData.Item1;
var dtos = newEntitiesData.Item2;
var newEntitiesData2 = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
var idDiscriminator2 = newEntitiesData2.Item1;
var dtos2 = newEntitiesData2.Item2;
//act
var result = await client.ClearAndAddRange(idDiscriminator, dtos, "Добавление новых элементов и очистка старых", CancellationToken.None);
var changeLogActualWithIdDiscriminator = await client.GetByDate(idDiscriminator2, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
var changeLogActualWithIdDiscriminator2 = await client.GetByDate(idDiscriminator, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
// assert
Assert.Equal(insertedCount * 2, result);
Assert.Equal(insertedCount, changeLogActualWithIdDiscriminator.Count);
Assert.Equal(insertedCount, changeLogActualWithIdDiscriminator2.Count);
}
[Fact]
public async Task AddRange_returns_success()
{
// arrange
var count = 3;
var idDiscriminator = Guid.NewGuid();
var dtos = Generate(count);
var comment = "Создаю 3 элемента";
// act
var result = await client.AddRange(idDiscriminator, dtos, comment, CancellationToken.None);
// assert
Assert.Equal(count, result);
}
[Fact]
public async Task Update_returns_success()
{
//arrange
dbContext.CleanupDbSet<ChangeLog>();
var idDiscriminator = Guid.NewGuid();
var dtos = Generate(1);
var dto = dtos.FirstOrDefault()!;
var comment = "Создаю 1 элемент";
var result = await client.AddRange(idDiscriminator, [dto], comment, CancellationToken.None);
var entity = dbContext.ChangeLog
.Where(x => x.DiscriminatorId == idDiscriminator)
.FirstOrDefault();
dto = entity.Adapt<ChangeLogValuesDto>();
// act
comment = "Обновляю 1 элемент";
result = await client.UpdateRange(idDiscriminator, [dto], comment, CancellationToken.None);
// assert
Assert.Equal(2, result);
var dateBegin = DateTimeOffset.UtcNow.AddDays(-1);
var dateEnd = DateTimeOffset.UtcNow.AddDays(1);
var changeLogResult = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, new CancellationToken());
Assert.NotNull(changeLogResult);
var obsoleteDto = changeLogResult
.Where(e => e.Obsolete.HasValue)
.FirstOrDefault();
var activeDto = changeLogResult
.Where(e => !e.Obsolete.HasValue)
.FirstOrDefault();
if (obsoleteDto == null || activeDto == null)
{
Assert.Fail();
return;
}
Assert.Equal(activeDto.Id, obsoleteDto.IdNext);
}
[Fact]
public async Task UpdateRange_returns_success()
{
var count = 2;
var idDiscriminator = Guid.NewGuid();
var dtos = Generate(count);
var comment = "Создаю 3 элемента";
// act
var result = await client.AddRange(idDiscriminator, dtos, comment, CancellationToken.None);
var paginatedResult = await client.GetByDate(idDiscriminator, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
// act
comment = "Обновляю 3 элемента";
result = await client.UpdateRange(idDiscriminator, paginatedResult.Items, comment, CancellationToken.None);
// assert
Assert.Equal(count * 2, result);
}
[Fact]
public async Task DeleteRange_returns_success()
{
// arrange
var insertedCount = 10;
var newEntitiesData = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
var idDiscriminator = newEntitiesData.Item1;
var dtos = newEntitiesData.Item2;
var newEntitiesData2 = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
var idDiscriminator2 = newEntitiesData2.Item1;
var dtos2 = newEntitiesData2.Item2;
// act
var ids = dtos.Select(e => e.Id);
var result = await client.DeleteRange(idDiscriminator, ids, "Удаление нескольких записей", CancellationToken.None);
// assert
Assert.Equal(insertedCount, result);
// act
var actualWithIdDescriminator = await client.GetByDate(idDiscriminator, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
var actualWithIdDescriminator2 = await client.GetByDate(idDiscriminator2, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
// assert
Assert.Equal(0, actualWithIdDescriminator.Count);
Assert.Equal(insertedCount, actualWithIdDescriminator2.Count);
}
[Fact]
public async Task GetDatesRange_returns_success()
{
//arrange
var changeLogItems = await CreateAndReturnNewEntities(3, (-15, -1));
var idDiscriminator = changeLogItems.Item1;
var entities = changeLogItems.Item2.OrderBy(c => c.Creation);
// act
var result = await client.GetDatesRange(idDiscriminator, CancellationToken.None);
// assert
Assert.NotNull(result);
var minDate = entities.First().Creation;
var maxDate = entities.Last().Creation;
var expectedMinDate = minDate.ToUniversalTime().ToString();
var actualMinDate = result.From.ToUniversalTime().ToString();
Assert.Equal(expectedMinDate, actualMinDate);
var expectedMaxDate = maxDate.ToUniversalTime().ToString();
var actualMaxDate = result.To.ToUniversalTime().ToString();
Assert.Equal(expectedMaxDate, actualMaxDate);
}
[Fact]
public async Task GetByDate_returns_success()
{
// arrange
dbContext.CleanupDbSet<ChangeLog>();
//создаем записи
var count = 5;
var changeLogItems = await CreateAndReturnNewDtos(count, (-15, -1));
var idDiscriminator = changeLogItems.Item1;
var entities = changeLogItems.Item2;
//удаляем все созданные записи за исключением первой и второй
//даты 2-х оставшихся записей должны вернуться в методе GetByDate
var ids = entities.Select(e => e.Id);
var idsToDelete = ids.Skip(2);
var deletedCount = await client.DeleteRange(idDiscriminator, idsToDelete, "Удаление нескольких записей", CancellationToken.None);
var moment = DateTimeOffset.UtcNow.AddDays(16);
var result = await client.GetByDate(idDiscriminator, moment, paginationRequest, new CancellationToken());
Assert.NotNull(result);
var restEntities = entities.Where(e => !idsToDelete.Contains(e.Id));
Assert.Equal(restEntities.Count(), result.Count);
var actualIds = restEntities.Select(e => e.Id);
var expectedIds = result.Items.Select(e => e.Id);
Assert.Equivalent(expectedIds, actualIds);
}
[Theory]
[InlineData(5, -15, -5, -20, 20, 10)]
[InlineData(5, -15, -10, -16, 9, 10)]
public async Task GetChangeLogForInterval_returns_success(
int insertedCount,
int daysBeforeNowChangeLog,
int daysAfterNowChangeLog,
int daysBeforeNowFilter,
int daysAfterNowFilter,
int changeLogCount)
{
// arrange
dbContext.CleanupDbSet<ChangeLog>();
//создаем записи
var count = insertedCount;
var daysRange = (daysBeforeNowChangeLog, daysAfterNowChangeLog);
var changeLogItems = await CreateAndReturnNewDtos(count, daysRange);
var idDiscriminator = changeLogItems.Item1;
var dtos = changeLogItems.Item2;
await client.UpdateRange(idDiscriminator, dtos, "Обновляем несколько записей", CancellationToken.None);
//act
var dateBegin = DateTimeOffset.UtcNow.AddDays(daysBeforeNowFilter);
var dateEnd = DateTimeOffset.UtcNow.AddDays(daysAfterNowFilter);
var result = await client.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, CancellationToken.None);
//assert
Assert.NotNull(result);
Assert.Equal(changeLogCount, result.Count());
}
[Theory]
[InlineData(10, 0, 10, 2, 10, 10)]
//[InlineData(10, 0, 0, 1, 10, 0)]
//[InlineData(2, 1, 1, 3, 2, 2)]
public async Task GetStatistics_returns_success(
int insertedCount,
int updatedCount,
int deletedCount,
int expectedCount,
int expectedInsertedCount,
int expectedObsoletedCount)
{
// arrange
dbContext.CleanupDbSet<ChangeLog>();
dbContext.CleanupDbSet<ChangeLogCommit>();
await dbContext.ChangeLogCommit.AddRangeAsync(Data.Defaults.ChangeLogCommits);
await dbContext.ChangeLog.AddRangeAsync(Data.Defaults.ChangeLogs);
await dbContext.SaveChangesAsync();
//создаем insertedCount записей c idDiscriminator по которому в последствии будем считать статистику
var createdDtos = await CreateAndReturnNewDtos(insertedCount, (-15, -1), new Guid("f7a1eed1-ef47-4360-9d4f-a30a0d8bb45e"));
var idDiscriminator = createdDtos.Item1;
var dtos = createdDtos.Item2;
//обновляем updatedCount записей
if(updatedCount > 0)
{
var updatedDtos = dtos.Take(updatedCount);
await client.UpdateRange(idDiscriminator, updatedDtos, "Коммит", CancellationToken.None);
}
//удаляем deletedCount записей
if (deletedCount > 0)
{
var deletedDtos = dtos.Take(deletedCount);
var deletedDtoIds = deletedDtos.Select(d => d.Id);
await client.DeleteRange(idDiscriminator, deletedDtoIds, "Коммит", CancellationToken.None);
}
//создаем insertedCount записей c другим idDiscriminator, чтобы проверить, что данный idDiscriminator не попал в статистику
var createdDtos2 = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
//act
//получаем статистику
var request = new ChangeLogRequest()
{
DiscriminatorId = idDiscriminator,
UserId = new Guid("067beb95-3b6d-7370-8000-1b9b336a6cdc")
};
var statistics = await client.GetStatistics(request, CancellationToken.None);
//assert
var dateTimeNow = DateTimeOffset.UtcNow;
var dateNow = new DateOnly(dateTimeNow.Year, dateTimeNow.Month, dateTimeNow.Day);
var currentDayStatistic = statistics.Where(s => s.Date == dateNow).FirstOrDefault();
if (currentDayStatistic == null)
Assert.Fail();
Assert.Equal(expectedCount, currentDayStatistic.CommitCount);
Assert.Equal(expectedInsertedCount, currentDayStatistic.CreatedChangeLogCount);
Assert.Equal(expectedObsoletedCount, currentDayStatistic.ObsoletedChangeLogCount);
}
private static IEnumerable<ChangeLogValuesDto> Generate(int count)
{
for (int i = 0; i < count; i++)
yield return new ChangeLogValuesDto()
{
Value = new Dictionary<string, object>()
{
{ "Key", 1 }
},
Id = Guid.NewGuid()
};
}
private async Task<(Guid, IEnumerable<ChangeLogValuesDto>)> CreateAndReturnNewDtos(int count, (int, int) daysRange, Guid? idDiscriminator = null)
{
var minDayCount = daysRange.Item1;
var maxDayCount = daysRange.Item2;
idDiscriminator = idDiscriminator ?? Uuid7.Guid();
var dtos = Generate(count);
var entities = dtos.Select(d =>
{
var entity = d.Adapt<ChangeLog>();
entity.DiscriminatorId = idDiscriminator.Value;
entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount));
return entity;
}).ToArray();
dtos = entities.Select(e => e.Adapt<ChangeLogValuesDto>());
// act
var result = await client.AddRange(idDiscriminator.Value, dtos, "Добавление элементов", CancellationToken.None);
var paginatedResult = await client.GetByDate(idDiscriminator.Value, DateTimeOffset.UtcNow.AddDays(1), paginationRequest, CancellationToken.None);
return (idDiscriminator.Value, paginatedResult.Items);
}
private async Task<(Guid, IEnumerable<ChangeLog>)> CreateAndReturnNewEntities(int count, (int, int) daysRange)
{
var commit = new ChangeLogCommit()
{
Comment = "Комментарий к коммиту",
Creation = DateTimeOffset.UtcNow,
Id = Guid.NewGuid(),
};
dbContext.ChangeLogCommit.Add(commit);
await dbContext.SaveChangesAsync();
var minDayCount = daysRange.Item1;
var maxDayCount = daysRange.Item2;
Guid idDiscriminator = Guid.NewGuid();
var dtos = Generate(count);
var entities = dtos.Select(d =>
{
var entity = d.Adapt<ChangeLog>();
entity.DiscriminatorId = idDiscriminator;
entity.Creation = commit.Creation;
entity.IdCreatedCommit = commit.Id;
return entity;
}).ToArray();
dbContext.ChangeLog.AddRange(entities);
await dbContext.SaveChangesAsync();
return (idDiscriminator, entities);
}
}