/
azarayaos
/
OrderHub
Обзор
Документация
Войти
/
azarayaos
/
OrderHub
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
dev
OrderHub.Tests/WebTests.cs
260 строк
9 KB
Azaray AOS
Добавлена APiпо авторизации и тесты для него. Так же пдготовлен файл CICD
01 июл 2026, 21:04
01 июл 2026, 21:04
9ff1e4b
Код
Авторство
О чём код?
using System.Net.Http.Headers; using System.Net.Http.Json; using Aspire.Hosting; using Microsoft.Extensions.Logging; using OrderHub.Core.DTOs; namespace OrderHub.IntegrationTests; /// <summary> /// Фикстура для интеграционных тестов OrderHub. Создаёт Aspire-хост один раз на все тесты класса. /// </summary> public class OrderHubTestFixture : IAsyncLifetime { private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(120); /// <summary> /// Запущенный Aspire-хост, общий для всех тестов. /// </summary> public DistributedApplication App { get; private set; } = null!; /// <summary> /// Создаёт и запускает Aspire-хост. /// </summary> public async ValueTask InitializeAsync() { var cancellationToken = CancellationToken.None; var appHost = await DistributedApplicationTestingBuilder.CreateAsync<Projects.OrderHub_AppHost>( ["--DISABLE_DATA_BIND_MOUNT=true"], cancellationToken); appHost.Services.AddLogging(logging => { logging.SetMinimumLevel(LogLevel.Debug); logging.AddFilter(appHost.Environment.ApplicationName, LogLevel.Debug); logging.AddFilter("Aspire.", LogLevel.Debug); }); appHost.Services.ConfigureHttpClientDefaults(clientBuilder => { clientBuilder.AddStandardResilienceHandler(); }); App = await appHost.BuildAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); await App.StartAsync(cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); var warmupClient = App.CreateHttpClient("apiservice"); await App.ResourceNotifications.WaitForResourceHealthyAsync("apiservice", cancellationToken).WaitAsync(DefaultTimeout, cancellationToken); warmupClient.Dispose(); } /// <summary> /// Останавливает и освобождает Aspire-хост. /// </summary> public async ValueTask DisposeAsync() { if (App is not null) { await App.DisposeAsync(); } } /// <summary> /// Создаёт новый HTTP-клиент для apiservice. /// </summary> /// <returns>Новый HTTP-клиент, привязанный к общему хосту.</returns> public HttpClient CreateClient() { return App.CreateHttpClient("apiservice"); } } /// <summary> /// Интеграционные тесты API заказов и аутентификации через Aspire TestHost. /// Используют общую фикстуру OrderHubTestFixture — хост создаётся один раз. /// </summary> public class OrderApiTests : IClassFixture<OrderHubTestFixture> { private readonly OrderHubTestFixture _fixture; /// <summary> /// Инициализирует тесты с общей фикстурой. /// </summary> /// <param name="fixture">Фикстура с запущенным Aspire-хостом.</param> public OrderApiTests(OrderHubTestFixture fixture) { _fixture = fixture; } /// <summary> /// Регистрирует нового пользователя и возвращает токен доступа. /// </summary> private static async Task<string> RegisterAndGetTokenAsync(HttpClient client, string email, string password = "TestPass1!") { var registerResponse = await client.PostAsJsonAsync("/api/auth/register", new { Email = email, Password = password }); registerResponse.EnsureSuccessStatusCode(); var loginResponse = await client.PostAsJsonAsync("/api/auth/login", new { Email = email, Password = password }); loginResponse.EnsureSuccessStatusCode(); var authData = await loginResponse.Content.ReadFromJsonAsync<AuthResponse>(); return authData!.Token; } /// <summary> /// POST /api/orders с JWT-токеном должен создавать заказ и возвращать 201. /// </summary> [Fact] public async Task CreateOrder_ReturnsCreatedOrder() { using var client = _fixture.CreateClient(); var email = $"create-order-{Guid.NewGuid():N}@test.com"; var token = await RegisterAndGetTokenAsync(client, email); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var createRequest = new CreateOrderRequest { Name = "Тестовый заказ", Items = new List<OrderItemDto> { new() { ProductName = "Тестовый товар", Quantity = 2, UnitPrice = 100.50m } } }; var response = await client.PostAsJsonAsync("/api/orders", createRequest); Assert.Equal(HttpStatusCode.Created, response.StatusCode); var orderResponse = await response.Content.ReadFromJsonAsync<OrderResponse>(); Assert.NotNull(orderResponse); Assert.Equal("Тестовый заказ", orderResponse.Name); Assert.Equal("Created", orderResponse.Status.ToString()); Assert.Single(orderResponse.Items); Assert.Equal(201.00m, orderResponse.TotalAmount); } /// <summary> /// POST /api/orders без токена должен возвращать 401. /// </summary> [Fact] public async Task CreateOrder_WithoutToken_ReturnsUnauthorized() { using var client = _fixture.CreateClient(); var createRequest = new CreateOrderRequest { Name = "Без токена", Items = new List<OrderItemDto> { new() { ProductName = "Товар", Quantity = 1, UnitPrice = 10m } } }; var response = await client.PostAsJsonAsync("/api/orders", createRequest); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } /// <summary> /// GET /api/orders с JWT-токеном должен возвращать список заказов. /// </summary> [Fact] public async Task GetOrders_ReturnsOrderList() { using var client = _fixture.CreateClient(); var email = $"get-orders-{Guid.NewGuid():N}@test.com"; var token = await RegisterAndGetTokenAsync(client, email); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var response = await client.GetAsync("/api/orders"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var orderList = await response.Content.ReadFromJsonAsync<OrderListResponse>(); Assert.NotNull(orderList); } /// <summary> /// Health check должен возвращать 200 (без аутентификации). /// </summary> [Fact] public async Task HealthCheck_ReturnsHealthy() { using var client = _fixture.CreateClient(); var response = await client.GetAsync("/api/health"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } /// <summary> /// POST /api/auth/register + POST /api/auth/login должны возвращать валидные токены. /// </summary> [Fact] public async Task RegisterAndLogin_ReturnsValidTokens() { using var client = _fixture.CreateClient(); var email = $"e2e-register-{Guid.NewGuid():N}@test.com"; var registerResponse = await client.PostAsJsonAsync("/api/auth/register", new { Email = email, Password = "TestPass1!" }); Assert.Equal(HttpStatusCode.Created, registerResponse.StatusCode); var registerAuth = await registerResponse.Content.ReadFromJsonAsync<AuthResponse>(); Assert.NotNull(registerAuth); Assert.NotEmpty(registerAuth!.Token); Assert.NotEmpty(registerAuth.RefreshToken); var loginResponse = await client.PostAsJsonAsync("/api/auth/login", new { Email = email, Password = "TestPass1!" }); Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode); var loginAuth = await loginResponse.Content.ReadFromJsonAsync<AuthResponse>(); Assert.Equal(email, loginAuth!.Email); Assert.Contains("User", loginAuth.Roles); } /// <summary> /// Администратор (засеянный при старте) может просматривать список пользователей. /// </summary> [Fact] public async Task AdminCanViewUsers() { using var client = _fixture.CreateClient(); var loginResponse = await client.PostAsJsonAsync("/api/auth/login", new { Email = "admin@orderhub.com", Password = "Admin123!" }); Assert.Equal(HttpStatusCode.OK, loginResponse.StatusCode); var adminAuth = await loginResponse.Content.ReadFromJsonAsync<AuthResponse>(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", adminAuth!.Token); var usersResponse = await client.GetAsync("/api/admin/users"); Assert.Equal(HttpStatusCode.OK, usersResponse.StatusCode); var userList = await usersResponse.Content.ReadFromJsonAsync<UserListResponse>(); Assert.NotNull(userList); Assert.NotEmpty(userList!.Users); Assert.Contains(userList.Users, u => u.Email == "admin@orderhub.com"); } }