Приборка в коде, рефакторинг, автотест для метода get DataSaubController

This commit is contained in:
Olga Nemt 2024-11-18 14:22:09 +05:00
parent 84e7ec274c
commit 531b14938f
28 changed files with 198 additions and 141 deletions

View File

@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Mvc;
using Persistence.API;
using Persistence.Repositories;
using Persistence.Repository.Data;
@ -11,5 +10,5 @@ public class DataSaubController : TimeSeriesController<DataSaubDto>
public DataSaubController(ITimeSeriesDataRepository<DataSaubDto> timeSeriesDataRepository) : base(timeSeriesDataRepository)
{
}
}
}

View File

@ -24,9 +24,10 @@ public class TimeSeriesController<TDto> : ControllerBase, ITimeSeriesDataApi<TDt
}
[HttpGet("datesRange")]
public Task<IActionResult> GetDatesRangeAsync(CancellationToken token)
public async Task<IActionResult> GetDatesRangeAsync(CancellationToken token)
{
throw new NotImplementedException();
var result = await this.timeSeriesDataRepository.GetDatesRangeAsync(token);
return Ok(result);
}
[HttpPost]

View File

@ -1,12 +0,0 @@
namespace Persistence.API;
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}

View File

@ -1,8 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Persistence.Database;
using Persistence.Database.Model;
namespace Persistence.Database.Model;

View File

@ -12,7 +12,7 @@ using Persistence.Database.Model;
namespace Persistence.Database.Postgres.Migrations
{
[DbContext(typeof(PersistenceDbContext))]
[Migration("20241115105149_InitialCreate")]
[Migration("20241118091712_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
@ -52,6 +52,10 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision")
.HasColumnName("blockSpeed");
b.Property<DateTimeOffset>("Date")
.HasColumnType("timestamp with time zone")
.HasColumnName("date");
b.Property<double?>("Flow")
.HasColumnType("double precision")
.HasColumnName("flow");
@ -100,10 +104,6 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision")
.HasColumnName("rotorTorque");
b.Property<int>("TimeStamp")
.HasColumnType("integer")
.HasColumnName("timestamp");
b.Property<string>("User")
.HasColumnType("text")
.HasColumnName("user");

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
@ -20,7 +21,7 @@ namespace Persistence.Database.Postgres.Migrations
{
id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
timestamp = table.Column<int>(type: "integer", nullable: false),
date = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
mode = table.Column<int>(type: "integer", nullable: true),
user = table.Column<string>(type: "text", nullable: true),
wellDepth = table.Column<double>(type: "double precision", nullable: true),

View File

@ -49,6 +49,10 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision")
.HasColumnName("blockSpeed");
b.Property<DateTimeOffset>("Date")
.HasColumnType("timestamp with time zone")
.HasColumnName("date");
b.Property<double?>("Flow")
.HasColumnType("double precision")
.HasColumnName("flow");
@ -97,10 +101,6 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("double precision")
.HasColumnName("rotorTorque");
b.Property<int>("TimeStamp")
.HasColumnType("integer")
.HasColumnName("timestamp");
b.Property<string>("User")
.HasColumnType("text")
.HasColumnName("user");

View File

@ -18,4 +18,8 @@
<ProjectReference Include="..\Persistence.Database\Persistence.Database.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
</Project>

View File

@ -4,10 +4,8 @@ using System.Data.Common;
namespace Persistence.Database.Model;
public partial class PersistenceDbContext : DbContext, IPersistenceDbContext
{
private readonly DbConnection connection = null!;
public DbSet<DataSaub> DataSaub => Set<DataSaub>();
public PersistenceDbContext()
: base()
{
@ -20,16 +18,6 @@ public partial class PersistenceDbContext : DbContext, IPersistenceDbContext
}
public PersistenceDbContext(DbConnection connection)
{
this.connection = connection;
}
protected virtual DbConnection GetConnection()
{
return connection;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)

View File

@ -6,8 +6,8 @@ public class DataSaub : ITimestampedData
[Column("id")]
public int Id { get; set; }
[Column("timestamp")]
public int TimeStamp { get; set; }
[Column("date")]
public DateTimeOffset Date { get; set; }
[Column("mode")]
public int? Mode { get; set; }

View File

@ -7,5 +7,8 @@ using System.Threading.Tasks;
namespace Persistence.Database.Model;
public interface ITimestampedData
{
int TimeStamp { get; set; }
/// <summary>
/// Дата (должна быть обязательно в UTC)
/// </summary>
DateTimeOffset Date { get; set; }
}

View File

@ -17,9 +17,9 @@ public abstract class BaseIntegrationTest : IClassFixture<WebAppFactoryFixture>,
protected BaseIntegrationTest(WebAppFactoryFixture factory)
{
//scope = factory.Services.CreateScope();
scope = factory.Services.CreateScope();
//dbContext = scope.ServiceProvider.GetRequiredService<PersistenceDbContext>();
dbContext = scope.ServiceProvider.GetRequiredService<PersistenceDbContext>();
}
public void Dispose()

View File

@ -1,11 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Persistence.Repository.Data;
using Refit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Persistence.IntegrationTests.Clients;
public interface ITimeSeriesClient<TDto>
@ -13,4 +7,7 @@ public interface ITimeSeriesClient<TDto>
{
[Post("/api/dataSaub")]
Task<IApiResponse<int>> InsertRangeAsync(IEnumerable<TDto> dtos);
[Get("/api/dataSaub")]
Task<IApiResponse<IEnumerable<TDto>>> GetAsync(DateTimeOffset dateBegin, DateTimeOffset dateEnd);
}

View File

@ -1,36 +1,56 @@
using Persistence.Repository.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Persistence.Database.Model;
using Persistence.Repository.Data;
using Xunit;
namespace Persistence.IntegrationTests.Controllers;
public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaubDto>
public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaub, DataSaubDto>
{
private readonly DataSaubDto dto = new DataSaubDto()
{
AxialLoad = 1,
BitDepth = 2,
BlockPosition = 3,
BlockSpeed = 4,
Date = DateTimeOffset.Now,
Flow = 5,
HookWeight = 6,
Id = 7,
IdFeedRegulator = 8,
Mode = 9,
Mse = 10,
MseState = 11,
Pressure = 12,
Pump0Flow = 13,
Pump1Flow = 14,
Pump2Flow = 15,
RotorSpeed = 16,
RotorTorque = 17,
User = string.Empty,
WellDepth = 18,
AxialLoad = 1,
BitDepth = 2,
BlockPosition = 3,
BlockSpeed = 4,
Date = DateTimeOffset.Now,
Flow = 5,
HookWeight = 6,
Id = 7,
IdFeedRegulator = 8,
Mode = 9,
Mse = 10,
MseState = 11,
Pressure = 12,
Pump0Flow = 13,
Pump1Flow = 14,
Pump2Flow = 15,
RotorSpeed = 16,
RotorTorque = 17,
User = string.Empty,
WellDepth = 18,
};
private readonly DataSaub entity = new DataSaub()
{
AxialLoad = 1,
BitDepth = 2,
BlockPosition = 3,
BlockSpeed = 4,
Date = DateTimeOffset.UtcNow,
Flow = 5,
HookWeight = 6,
Id = 7,
IdFeedRegulator = 8,
Mode = 9,
Mse = 10,
MseState = 11,
Pressure = 12,
Pump0Flow = 13,
Pump1Flow = 14,
Pump2Flow = 15,
RotorSpeed = 16,
RotorTorque = 17,
User = string.Empty,
WellDepth = 18,
};
public DataSaubControllerTest(WebAppFactoryFixture factory) : base(factory)
@ -42,4 +62,12 @@ public class DataSaubControllerTest : TimeSeriesBaseControllerTest<DataSaubDto>
{
await InsertRangeSuccess(dto);
}
[Fact]
public async Task Get_returns_success()
{
var beginDate = DateTimeOffset.UtcNow.AddDays(-1);
var endDate = DateTimeOffset.UtcNow;
await GetSuccess(beginDate, endDate, entity);
}
}

View File

@ -1,6 +1,7 @@
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration.UserSecrets;
using Persistence.IntegrationTests.Clients;
using Persistence.Models;
using System;
@ -12,14 +13,15 @@ using System.Threading.Tasks;
using Xunit;
namespace Persistence.IntegrationTests.Controllers;
public abstract class TimeSeriesBaseControllerTest<TDto> : BaseIntegrationTest
public abstract class TimeSeriesBaseControllerTest<TEntity, TDto> : BaseIntegrationTest
where TEntity : class
where TDto : class, new()
{
private ITimeSeriesClient<TDto> client;
public TimeSeriesBaseControllerTest(WebAppFactoryFixture factory) : base(factory)
{
//dbContext.CleanupDbSet<TEntity>();
dbContext.CleanupDbSet<TEntity>();
client = factory.GetHttpClient<ITimeSeriesClient<TDto>>(string.Empty);
}
@ -34,18 +36,22 @@ public abstract class TimeSeriesBaseControllerTest<TDto> : BaseIntegrationTest
//assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(1, response.Content);
}
//var entity = GetByWellId();
public async Task GetSuccess(DateTimeOffset beginDate, DateTimeOffset endDate, TEntity entity)
{
//arrange
var dbset = dbContext.Set<TEntity>();
//Assert.NotNull(entity);
dbset.Add(entity);
//var actual = entity.Adapt<ChangeLogDto<TDto>>();
//Assert.Equal(ProcessMapPlanBase.IdStateActual, actual.IdState);
dbContext.SaveChanges();
//var excludeProps = new[] {
// nameof(ProcessMapPlanBaseDto.Id),
// nameof(ProcessMapPlanBaseDto.Section)
//};
//MatchHelper.Match(expected, actual.Item, excludeProps);
var response = await client.GetAsync(beginDate, endDate);
//assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotNull(response.Content);
Assert.Single(response.Content);
}
}

View File

@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using Persistence.Database.Model;
namespace Persistence.IntegrationTests;
public static class EFCoreExtensions
{
public static void CleanupDbSet<T>(this DbContext dbContext)
where T : class
{
var dbset = dbContext.Set<T>();
dbset.RemoveRange(dbset);
dbContext.SaveChanges();
}
}

View File

@ -24,6 +24,7 @@
<ItemGroup>
<ProjectReference Include="..\Persistence.API\Persistence.API.csproj" />
<ProjectReference Include="..\Persistence.Database.Postgres\Persistence.Database.Postgres.csproj" />
</ItemGroup>
</Project>

View File

@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Persistence.Database.Model;
using Persistence.Database.Postgres;
using Persistence.API;
using Refit;
using System.Net.Http.Headers;
using System.Text.Json;
namespace Persistence.IntegrationTests;
@ -51,7 +51,7 @@ public class WebAppFactoryFixture : WebApplicationFactory<Startup>
var scopedServices = scope.ServiceProvider;
var dbContext = scopedServices.GetRequiredService<PersistenceDbContext>();
//dbContext.Database.EnsureCreatedAndMigrated();
dbContext.Database.EnsureCreatedAndMigrated();
//dbContext.Deposits.AddRange(Data.Defaults.Deposits);
dbContext.SaveChanges();
});

View File

@ -1,14 +1,12 @@
using Mapster;
using Microsoft.EntityFrameworkCore;
using Persistence.Database.Model;
using Persistence.Models;
using Persistence.Repositories;
using Persistence.Database.Model;
using Persistence.Repository.Data;
using Persistence.Database;
namespace Persistence.Repository.Repositories;
public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository<TDto>
where TEntity : class
where TEntity : class, ITimestampedData, new()
where TDto : class, ITimeSeriesAbstractDto, new()
{
private DbContext db;
@ -29,14 +27,27 @@ public class TimeSeriesDataRepository<TEntity, TDto> : ITimeSeriesDataRepository
return dtos;
}
public Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
public async Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
{
throw new NotImplementedException();
var query = GetQueryReadOnly();
var minDate = await query.MinAsync(o => o.Date, token);
var maxDate = await query.MaxAsync(o => o.Date, token);
return new DatesRangeDto
{
From = minDate,
To = maxDate
};
}
public Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
public async Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
{
throw new NotImplementedException();
var query = this.db.Set<TEntity>().Where(e => e.Date > date);
var entities = await query.ToArrayAsync(token);
var dtos = entities.Select(e => e.Adapt<TDto>());
return dtos;
}
public async Task<int> InsertRange(IEnumerable<TDto> dtos, CancellationToken token)

View File

@ -5,9 +5,19 @@ using System.Text;
using System.Threading.Tasks;
namespace Persistence.Models;
/// <summary>
/// Диапазон дат
/// </summary>
public class DatesRangeDto
{
public DateTimeOffset dateBegin { get; set; }
/// <summary>
/// Дата начала диапазона
/// </summary>
public DateTimeOffset From { get; set; }
public DateTimeOffset dateEnd { get; set; }
/// <summary>
/// Дата окончания диапазона
/// </summary>
public DateTimeOffset To { get; set; }
}

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Persistence.Models;
namespace Persistence.Models;
/// <summary>
/// Интерфейс, описывающий временные данные

View File

@ -1,10 +1,23 @@
namespace Persistence.Models;
/// <summary>
/// Контейнер для поддержки постраничного просмотра таблиц
/// </summary>
/// <typeparam name="T"></typeparam>
public class RequestDto
{
/// <summary>
/// Кол-во записей пропущенных с начала таблицы в запросе от api
/// </summary>
public int Skip { get; set; }
/// <summary>
/// Кол-во записей в запросе от api
/// </summary>
public int Take { get; set; }
/// <summary>
/// Настройки сортировки
/// </summary>
public string SortSettings { get; set; } = string.Empty;
}

View File

@ -1,12 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Persistence.Models;
namespace Persistence.Models;
/// <summary>
/// Модель для описания лога уставки
/// </summary>
public class SetpointLogDto : SetpointValueDto
{
public DateTimeOffset Edit { get; set; }
/// <summary>
/// Дата сохранения уставки
/// </summary>
public DateTimeOffset DateEdit { get; set; }
/// <summary>
/// Ключ пользователя
/// </summary>
public int IdUser { get; set; }
}

View File

@ -1,14 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Persistence.Models;
namespace Persistence.Models;
/// <summary>
/// Модель для хранения значения уставки
/// </summary>
public class SetpointValueDto
{
/// <summary>
/// Идентификатор уставки
/// </summary>
public int Id { get; set; }
/// <summary>
/// Значение уставки
/// </summary>
public object Value { get; set; }
}

View File

@ -1,11 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Persistence.Models;
namespace Persistence.Models;
/// <summary>
/// Модель, описывающая пользователя
/// </summary>
public class UserDto
{
/// <inheritdoc/>

View File

@ -1,10 +1,4 @@
using Microsoft.AspNetCore.Mvc;
using Persistence.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Persistence.Models;
namespace Persistence.Repositories;
@ -13,7 +7,7 @@ namespace Persistence.Repositories;
/// </summary>
public interface ISetpointRepository
{
/// <summary>
/// Получить значения уставок за определенный момент времени
/// </summary>

View File

@ -1,12 +1,12 @@
namespace Persistence.Services;
/// <summary>
///
/// Сервис по работе с БД
/// </summary>
internal interface IArchiveService
{
/// <summary>
///
/// Переименование БД
/// </summary>
/// <param name="connectionString"></param>
/// <param name="databaseName"></param>
@ -15,7 +15,7 @@ internal interface IArchiveService
Task RenameDatabase(string connectionString, string databaseName, CancellationToken token);
/// <summary>
///
/// Создание БД
/// </summary>
/// <param name="connectionString"></param>
/// <param name="databaseName"></param>

View File

@ -1,4 +1,5 @@
namespace Persistence.Services;
public interface ITimeSeriesDataObserverService
{
}