diff --git a/Persistence.Client/Clients/ISetpointClient.cs b/Persistence.Client/Clients/ISetpointClient.cs new file mode 100644 index 0000000..49733f0 --- /dev/null +++ b/Persistence.Client/Clients/ISetpointClient.cs @@ -0,0 +1,24 @@ +using Persistence.Models; +using Refit; + +namespace Persistence.Client.Clients; + +/// +/// Интерфейс для тестирования API, предназначенного для работы с уставками +/// +public interface ISetpointClient +{ + private const string BaseRoute = "/api/setpoint"; + + [Get($"{BaseRoute}/current")] + Task>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); + + [Get($"{BaseRoute}/history")] + Task>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, [Query] DateTimeOffset historyMoment); + + [Get($"{BaseRoute}/log")] + Task>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); + + [Post($"{BaseRoute}/")] + Task Save(Guid setpointKey, object newValue); +} diff --git a/Persistence.IntegrationTests/Clients/ITimeSeriesClient.cs b/Persistence.Client/Clients/ITimeSeriesClient.cs similarity index 88% rename from Persistence.IntegrationTests/Clients/ITimeSeriesClient.cs rename to Persistence.Client/Clients/ITimeSeriesClient.cs index 03b7638..8456fa2 100644 --- a/Persistence.IntegrationTests/Clients/ITimeSeriesClient.cs +++ b/Persistence.Client/Clients/ITimeSeriesClient.cs @@ -1,7 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Refit; -namespace Persistence.IntegrationTests.Clients; +namespace Persistence.Client.Clients; public interface ITimeSeriesClient where TDto : class, new() { diff --git a/Persistence.Client/Helpers/ApiTokenHelper.cs b/Persistence.Client/Helpers/ApiTokenHelper.cs new file mode 100644 index 0000000..479ba60 --- /dev/null +++ b/Persistence.Client/Helpers/ApiTokenHelper.cs @@ -0,0 +1,43 @@ +namespace Persistence.Client.Helpers; +public static class ApiTokenHelper +{ + public static string GetAdminUserToken() + { + //var user = new User() + //{ + // Id = 1, + // IdCompany = 1, + // Login = "test_user" + //}; + //var roles = new[] { "root" }; + + return string.Empty; + } + + //private static string CreateToken(User user, IEnumerable roles) + //{ + // var claims = new List + // { + // new("id", user.Id.ToString()), + // new(ClaimsIdentity.DefaultNameClaimType, user.Login), + // new("idCompany", user.IdCompany.ToString()), + // }; + + // claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role))); + + // const string secret = "супер секретный ключ для шифрования"; + + // var key = Encoding.ASCII.GetBytes(secret); + // var tokenDescriptor = new SecurityTokenDescriptor + // { + // Issuer = "a", + // Audience = "a", + // Subject = new ClaimsIdentity(claims), + // Expires = DateTime.UtcNow.AddHours(1), + // SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) + // }; + // var tokenHandler = new JwtSecurityTokenHandler(); + // var token = tokenHandler.CreateToken(tokenDescriptor); + // return tokenHandler.WriteToken(token); + //} +} diff --git a/Persistence.Client/Persistence.Client.csproj b/Persistence.Client/Persistence.Client.csproj new file mode 100644 index 0000000..c7ed8f5 --- /dev/null +++ b/Persistence.Client/Persistence.Client.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/Persistence.Client/PersistenceClientFactory.cs b/Persistence.Client/PersistenceClientFactory.cs new file mode 100644 index 0000000..9c3be71 --- /dev/null +++ b/Persistence.Client/PersistenceClientFactory.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http.Headers; +using System.Net.Http; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using Refit; +using Persistence.Client.Helpers; + +namespace Persistence.Client +{ + public static class PersistenceClientFactory + { + + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true + }; + + private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); + + public static T GetClient(HttpClient client) + { + return RestService.For(client, RefitSettings); + } + + public static T GetClient(string baseUrl) + { + var client = new HttpClient(); + client.BaseAddress = new Uri(baseUrl); + + return RestService.For(client, RefitSettings); + } + + private static HttpClient GetAuthorizedClient() + { + var httpClient = new HttpClient(); + var jwtToken = ApiTokenHelper.GetAdminUserToken(); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken); + + return httpClient; + } + } +} diff --git a/Persistence.IntegrationTests/Clients/ISetpointClient.cs b/Persistence.IntegrationTests/Clients/ISetpointClient.cs deleted file mode 100644 index a4f79b5..0000000 --- a/Persistence.IntegrationTests/Clients/ISetpointClient.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Persistence.Models; -using Refit; - -namespace Persistence.IntegrationTests.Clients -{ - /// - /// Интерфейс для тестирования API, предназначенного для работы с уставками - /// - public interface ISetpointClient - { - private const string BaseRoute = "/api/setpoint"; - - [Get($"{BaseRoute}/current")] - Task>> GetCurrent([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); - - [Get($"{BaseRoute}/history")] - Task>> GetHistory([Query(CollectionFormat.Multi)] IEnumerable setpointKeys, [Query] DateTimeOffset historyMoment); - - [Get($"{BaseRoute}/log")] - Task>>> GetLog([Query(CollectionFormat.Multi)] IEnumerable setpointKeys); - - [Post($"{BaseRoute}/")] - Task Save(Guid setpointKey, object newValue); - } -} diff --git a/Persistence.IntegrationTests/Controllers/DataSaubControllerTest.cs b/Persistence.IntegrationTests/Controllers/DataSaubControllerTest.cs index 025492a..8708960 100644 --- a/Persistence.IntegrationTests/Controllers/DataSaubControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/DataSaubControllerTest.cs @@ -1,4 +1,5 @@ -using Persistence.Database.Model; +using Persistence.Client; +using Persistence.Database.Model; using Persistence.Repository.Data; using Xunit; diff --git a/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs b/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs index 2fcfc52..f865ce2 100644 --- a/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/SetpointControllerTest.cs @@ -1,12 +1,14 @@ using System.Net; -using Persistence.IntegrationTests.Clients; +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client; +using Persistence.Client.Clients; using Xunit; namespace Persistence.IntegrationTests.Controllers { public class SetpointControllerTest : BaseIntegrationTest { - private ISetpointClient client; + private ISetpointClient setpointClient; private class TestObject { public string? value1 { get; set; } @@ -14,7 +16,12 @@ namespace Persistence.IntegrationTests.Controllers } public SetpointControllerTest(WebAppFactoryFixture factory) : base(factory) { - client = factory.GetHttpClient(string.Empty); + var scope = factory.Services.CreateScope(); + var httpClient = scope.ServiceProvider + .GetRequiredService() + .CreateClient(); + + setpointClient = PersistenceClientFactory.GetClient(httpClient); } [Fact] @@ -28,7 +35,7 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await client.GetCurrent(setpointKeys); + var response = await setpointClient.GetCurrent(setpointKeys); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -43,7 +50,7 @@ namespace Persistence.IntegrationTests.Controllers var setpointKey = await Save(); //act - var response = await client.GetCurrent([setpointKey]); + var response = await setpointClient.GetCurrent([setpointKey]); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -64,7 +71,7 @@ namespace Persistence.IntegrationTests.Controllers var historyMoment = DateTimeOffset.UtcNow; //act - var response = await client.GetHistory(setpointKeys, historyMoment); + var response = await setpointClient.GetHistory(setpointKeys, historyMoment); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -81,7 +88,7 @@ namespace Persistence.IntegrationTests.Controllers historyMoment = historyMoment.AddDays(1); //act - var response = await client.GetHistory([setpointKey], historyMoment); + var response = await setpointClient.GetHistory([setpointKey], historyMoment); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -101,7 +108,7 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await client.GetLog(setpointKeys); + var response = await setpointClient.GetLog(setpointKeys); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -116,7 +123,7 @@ namespace Persistence.IntegrationTests.Controllers var setpointKey = await Save(); //act - var response = await client.GetLog([setpointKey]); + var response = await setpointClient.GetLog([setpointKey]); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -142,7 +149,7 @@ namespace Persistence.IntegrationTests.Controllers }; //act - var response = await client.Save(setpointKey, setpointValue); + var response = await setpointClient.Save(setpointKey, setpointValue); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); diff --git a/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs b/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs index c63f094..59623a1 100644 --- a/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs +++ b/Persistence.IntegrationTests/Controllers/TimeSeriesBaseControllerTest.cs @@ -1,15 +1,8 @@ -using Mapster; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration.UserSecrets; -using Persistence.IntegrationTests.Clients; -using Persistence.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; +using System.Net; +using Mapster; +using Microsoft.Extensions.DependencyInjection; +using Persistence.Client; +using Persistence.Client.Clients; using Xunit; namespace Persistence.IntegrationTests.Controllers; @@ -17,13 +10,18 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat where TEntity : class where TDto : class, new() { - private ITimeSeriesClient client; + private ITimeSeriesClient timeSeriesClient; public TimeSeriesBaseControllerTest(WebAppFactoryFixture factory) : base(factory) { dbContext.CleanupDbSet(); - client = factory.GetAuthorizedHttpClient>(string.Empty); + var scope = factory.Services.CreateScope(); + var httpClient = scope.ServiceProvider + .GetRequiredService() + .CreateClient(); + + timeSeriesClient = PersistenceClientFactory.GetClient>(httpClient); } public async Task InsertRangeSuccess(TDto dto) @@ -32,7 +30,7 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat var expected = dto.Adapt(); //act - var response = await client.InsertRangeAsync(new TDto[] { expected }); + var response = await timeSeriesClient.InsertRangeAsync(new TDto[] { expected }); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -48,7 +46,7 @@ public abstract class TimeSeriesBaseControllerTest : BaseIntegrat dbContext.SaveChanges(); - var response = await client.GetAsync(beginDate, endDate); + var response = await timeSeriesClient.GetAsync(beginDate, endDate); //assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); diff --git a/Persistence.IntegrationTests/Persistence.IntegrationTests.csproj b/Persistence.IntegrationTests/Persistence.IntegrationTests.csproj index 912eeda..7d0116e 100644 --- a/Persistence.IntegrationTests/Persistence.IntegrationTests.csproj +++ b/Persistence.IntegrationTests/Persistence.IntegrationTests.csproj @@ -24,6 +24,7 @@ + diff --git a/Persistence.IntegrationTests/TestHttpClientFactory.cs b/Persistence.IntegrationTests/TestHttpClientFactory.cs new file mode 100644 index 0000000..1687f49 --- /dev/null +++ b/Persistence.IntegrationTests/TestHttpClientFactory.cs @@ -0,0 +1,16 @@ +namespace Persistence.IntegrationTests +{ + public class TestHttpClientFactory : IHttpClientFactory + { + private readonly WebAppFactoryFixture factory; + + public TestHttpClientFactory(WebAppFactoryFixture factory) + { + this.factory = factory; + } + public HttpClient CreateClient(string name) + { + return factory.CreateClient(); + } + } +} diff --git a/Persistence.IntegrationTests/WebAppFactoryFixture.cs b/Persistence.IntegrationTests/WebAppFactoryFixture.cs index ac73013..f932b83 100644 --- a/Persistence.IntegrationTests/WebAppFactoryFixture.cs +++ b/Persistence.IntegrationTests/WebAppFactoryFixture.cs @@ -10,6 +10,8 @@ using Refit; using System.Text.Json; using Persistence.Database.Postgres; using System.Net.Http.Headers; +using Persistence.Client; +using Microsoft.Extensions.DependencyInjection.Extensions; namespace Persistence.IntegrationTests; public class WebAppFactoryFixture : WebApplicationFactory @@ -47,57 +49,21 @@ public class WebAppFactoryFixture : WebApplicationFactory services.AddDbContext(options => options.UseNpgsql(connectionString)); - var serviceProvider = services.BuildServiceProvider(); + services.RemoveAll(); + services.AddSingleton(provider => + { + return new TestHttpClientFactory(this); + }); + + var serviceProvider = services.BuildServiceProvider(); using var scope = serviceProvider.CreateScope(); var scopedServices = scope.ServiceProvider; - var dbContext = scopedServices.GetRequiredService(); + var dbContext = scopedServices.GetRequiredService(); dbContext.Database.EnsureCreatedAndMigrated(); //dbContext.Deposits.AddRange(Data.Defaults.Deposits); dbContext.SaveChanges(); }); } - - public override async ValueTask DisposeAsync() - { - var dbContext = new PersistenceDbContext( - new DbContextOptionsBuilder() - .UseNpgsql(connectionString) - .Options); - - await dbContext.Database.EnsureDeletedAsync(); - } - - public T GetHttpClient(string uriSuffix) - { - var httpClient = CreateClient(); - if (string.IsNullOrEmpty(uriSuffix)) - return RestService.For(httpClient, RefitSettings); - - if (httpClient.BaseAddress is not null) - httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); - - return RestService.For(httpClient, RefitSettings); - } - - public T GetAuthorizedHttpClient(string uriSuffix) - { - var httpClient = GetAuthorizedHttpClient(); - if (string.IsNullOrEmpty(uriSuffix)) - return RestService.For(httpClient, RefitSettings); - - if (httpClient.BaseAddress is not null) - httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); - - return RestService.For(httpClient, RefitSettings); - } - - private HttpClient GetAuthorizedHttpClient() - { - var httpClient = CreateClient(); - ////var jwtToken = ApiTokenHelper.GetAdminUserToken(); - //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken); - return httpClient; - } } diff --git a/Persistence.sln b/Persistence.sln index ce44190..a8115a8 100644 --- a/Persistence.sln +++ b/Persistence.sln @@ -13,7 +13,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Database", "Per EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.IntegrationTests", "Persistence.IntegrationTests\Persistence.IntegrationTests.csproj", "{10752C25-3773-4081-A1F2-215A1D950126}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Persistence.Database.Postgres", "Persistence.Database.Postgres\Persistence.Database.Postgres.csproj", "{CC284D27-162D-490C-B6CF-74D666B7C5F3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Persistence.Database.Postgres", "Persistence.Database.Postgres\Persistence.Database.Postgres.csproj", "{CC284D27-162D-490C-B6CF-74D666B7C5F3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Persistence.Client", "Persistence.Client\Persistence.Client.csproj", "{84B68660-48E6-4974-A4E5-517552D9DE23}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -45,6 +47,10 @@ Global {CC284D27-162D-490C-B6CF-74D666B7C5F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CC284D27-162D-490C-B6CF-74D666B7C5F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {CC284D27-162D-490C-B6CF-74D666B7C5F3}.Release|Any CPU.Build.0 = Release|Any CPU + {84B68660-48E6-4974-A4E5-517552D9DE23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84B68660-48E6-4974-A4E5-517552D9DE23}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84B68660-48E6-4974-A4E5-517552D9DE23}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84B68660-48E6-4974-A4E5-517552D9DE23}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE