diff --git a/src/AzureOpenAIProxy.ApiApp/Endpoints/AdminEventEndpoints.cs b/src/AzureOpenAIProxy.ApiApp/Endpoints/AdminEventEndpoints.cs index b877754b..6df29391 100644 --- a/src/AzureOpenAIProxy.ApiApp/Endpoints/AdminEventEndpoints.cs +++ b/src/AzureOpenAIProxy.ApiApp/Endpoints/AdminEventEndpoints.cs @@ -34,22 +34,20 @@ public static RouteHandlerBuilder AddNewAdminEvent(this WebApplication app) return Results.BadRequest("Payload is null"); } - //try - //{ - // var result = await service.CreateEvent(payload); - - // logger.LogInformation("Created a new event"); + try + { + var result = await service.CreateEvent(payload); - // return Results.Ok(result); - //} - //catch (Exception ex) - //{ - // logger.LogError(ex, "Failed to create a new event"); + logger.LogInformation("Created a new event"); - // return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); - //} + return Results.Ok(result); + } + catch (Exception ex) + { + logger.LogError(ex, "Failed to create a new event"); - return await Task.FromResult(Results.Ok()); + return Results.Problem(ex.Message, statusCode: StatusCodes.Status500InternalServerError); + } }) .Accepts(contentType: "application/json") .Produces(statusCode: StatusCodes.Status200OK, contentType: "application/json") diff --git a/src/AzureOpenAIProxy.ApiApp/Models/AdminEventDetails.cs b/src/AzureOpenAIProxy.ApiApp/Models/AdminEventDetails.cs index aa5dc597..57e3b8e0 100644 --- a/src/AzureOpenAIProxy.ApiApp/Models/AdminEventDetails.cs +++ b/src/AzureOpenAIProxy.ApiApp/Models/AdminEventDetails.cs @@ -1,5 +1,8 @@ using System.Text.Json.Serialization; +using Azure; +using Azure.Data.Tables; + namespace AzureOpenAIProxy.ApiApp.Models; /// diff --git a/src/AzureOpenAIProxy.ApiApp/Repositories/AdminEventRepository.cs b/src/AzureOpenAIProxy.ApiApp/Repositories/AdminEventRepository.cs index 1ef0dfcb..3adb60a2 100644 --- a/src/AzureOpenAIProxy.ApiApp/Repositories/AdminEventRepository.cs +++ b/src/AzureOpenAIProxy.ApiApp/Repositories/AdminEventRepository.cs @@ -51,7 +51,14 @@ public class AdminEventRepository(TableServiceClient tableServiceClient, Storage /// public async Task CreateEvent(AdminEventDetails eventDetails) { - throw new NotImplementedException(); + // 테이블 클라이언트 + TableClient tableClient = await GetTableClientAsync(); + + // 데이터 저장 + await tableClient.AddEntityAsync(eventDetails).ConfigureAwait(false); + + // 저장한 엔티티 반환 + return eventDetails; } /// diff --git a/src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs b/src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs index 09f21797..a5289023 100644 --- a/src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs +++ b/src/AzureOpenAIProxy.ApiApp/Services/AdminEventService.cs @@ -47,9 +47,13 @@ public class AdminEventService(IAdminEventRepository repository) : IAdminEventSe /// public async Task CreateEvent(AdminEventDetails eventDetails) { - var result = await this._repository.CreateEvent(eventDetails).ConfigureAwait(false); - - return result; + // Validate + eventDetails.PartitionKey = PartitionKeys.EventDetails; + eventDetails.RowKey = eventDetails.EventId.ToString(); + + // Save + var response = await this._repository.CreateEvent(eventDetails).ConfigureAwait(false); + return response; } /// diff --git a/src/AzureOpenAIProxy.ApiApp/appsettings.Development.sample.json b/src/AzureOpenAIProxy.ApiApp/appsettings.Development.sample.json index 534af650..1b4b4928 100644 --- a/src/AzureOpenAIProxy.ApiApp/appsettings.Development.sample.json +++ b/src/AzureOpenAIProxy.ApiApp/appsettings.Development.sample.json @@ -1,27 +1,30 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - - "Azure": { - "OpenAI": { - "Instances": [ - { - "Endpoint": "https://{{location}}.api.cognitive.microsoft.com/", - "ApiKey": "{{api-key}}", - "DeploymentNames": [ - "deployment-name-1", - "deployment-name-2" - ] - } - ] - }, - "KeyVault": { - "VaultUri": "https://{{key-vault-name}}.vault.azure.net/", - "SecretName": "azure-openai-instances" - } - } -} +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + + "Azure": { + "OpenAI": { + "Instances": [ + { + "Endpoint": "https://{{location}}.api.cognitive.microsoft.com/", + "ApiKey": "{{api-key}}", + "DeploymentNames": [ + "deployment-name-1", + "deployment-name-2" + ] + } + ] + }, + "KeyVault": { + "VaultUri": "https://{{key-vault-name}}.vault.azure.net/", + "SecretNames": { + "OpenAI": "azure-openai-instances", + "Storage": "storage-connection-string" + } + } + } +} diff --git a/test/AzureOpenAIProxy.ApiApp.Tests/Repositories/AdminEventRepositoryTests.cs b/test/AzureOpenAIProxy.ApiApp.Tests/Repositories/AdminEventRepositoryTests.cs index ddc0facd..3278cca4 100644 --- a/test/AzureOpenAIProxy.ApiApp.Tests/Repositories/AdminEventRepositoryTests.cs +++ b/test/AzureOpenAIProxy.ApiApp.Tests/Repositories/AdminEventRepositoryTests.cs @@ -58,19 +58,46 @@ public void Given_Null_StorageAccountSettings_When_Creating_AdminEventRepository } [Fact] - public void Given_Instance_When_CreateEvent_Invoked_Then_It_Should_Throw_Exception() + public async Task Given_Instance_When_CreateEvent_Invoked_Then_It_Should_Return_Passed_Argument() { // Arrange var settings = Substitute.For(); var tableServiceClient = Substitute.For(); + var tableClient = Substitute.For(); + tableServiceClient.GetTableClient(Arg.Any()).Returns(tableClient); + tableClient.AddEntityAsync(Arg.Any()) + .Returns(Task.FromResult(default(Response))); var eventDetails = new AdminEventDetails(); var repository = new AdminEventRepository(tableServiceClient, settings); // Act - Func func = async () => await repository.CreateEvent(eventDetails); + var result = await repository.CreateEvent(eventDetails); // Assert - func.Should().ThrowAsync(); + result.Should().BeEquivalentTo(eventDetails); + } + + [Fact] + public async Task Given_Failure_In_Add_Entity_When_CreateEvent_Invoked_Then_It_Should_Throw_Exception() + { + // Arrange + var settings = Substitute.For(); + var tableServiceClient = Substitute.For(); + var repository = new AdminEventRepository(tableServiceClient, settings); + var eventDetails = new AdminEventDetails(); + + var exception = new InvalidOperationException("Invalid Operation Error : check duplicate, null or empty values"); + + var tableClient = Substitute.For(); + tableServiceClient.GetTableClient(Arg.Any()).Returns(tableClient); + tableClient.AddEntityAsync(Arg.Any()) + .ThrowsAsync(exception); + + // Act + Func func = () => repository.CreateEvent(eventDetails); + + // Assert + await func.Should().ThrowAsync(); } [Fact] diff --git a/test/AzureOpenAIProxy.ApiApp.Tests/Services/AdminEventServiceTests.cs b/test/AzureOpenAIProxy.ApiApp.Tests/Services/AdminEventServiceTests.cs index f0442c76..4ba483a1 100644 --- a/test/AzureOpenAIProxy.ApiApp.Tests/Services/AdminEventServiceTests.cs +++ b/test/AzureOpenAIProxy.ApiApp.Tests/Services/AdminEventServiceTests.cs @@ -6,6 +6,8 @@ using FluentAssertions; +using Microsoft.AspNetCore.Authentication; + using Microsoft.Extensions.DependencyInjection; using NSubstitute; @@ -29,18 +31,39 @@ public void Given_ServiceCollection_When_AddAdminEventService_Invoked_Then_It_Sh } [Fact] - public void Given_Instance_When_CreateEvent_Invoked_Then_It_Should_Throw_Exception() + public async Task Given_Instance_When_CreateEvent_Invoked_Then_It_Should_Return_Passed_Argument() { // Arrange var eventDetails = new AdminEventDetails(); + var repository = Substitute.For(); var service = new AdminEventService(repository); + repository.CreateEvent(Arg.Any()).Returns(eventDetails); + // Act - Func func = async () => await service.CreateEvent(eventDetails); + var result = await service.CreateEvent(eventDetails); // Assert - func.Should().ThrowAsync(); + result.Should().BeEquivalentTo(eventDetails); + } + + [Fact] + public async Task Given_Failure_In_Add_Entity_When_CreateEvent_Invoked_Then_It_Should_Throw_Exception() + { + // Arrange + var eventDetails = new AdminEventDetails(); + var repository = Substitute.For(); + var service = new AdminEventService(repository); + + var exception = new InvalidOperationException("Invalid Operation Error : check duplicate, null or empty values"); + repository.CreateEvent(Arg.Any()).ThrowsAsync(exception); + + // Act + Func func = () => service.CreateEvent(eventDetails); + + // Assert + await func.Should().ThrowAsync(); } [Fact] diff --git a/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/AdminGetEventsOpenApiTests.cs b/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/AdminGetEventsOpenApiTests.cs index c0180f1b..1aa8482a 100644 --- a/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/AdminGetEventsOpenApiTests.cs +++ b/test/AzureOpenAIProxy.AppHost.Tests/ApiApp/Endpoints/AdminGetEventsOpenApiTests.cs @@ -8,7 +8,6 @@ namespace AzureOpenAIProxy.AppHost.Tests.ApiApp.Endpoints; public class AdminGetEventsOpenApiTests(AspireAppHostFixture host) : IClassFixture { - // TODO: [tae0y] 테스트코드 작성하기 [Fact] public async Task Given_Resource_When_Invoked_Endpoint_Then_It_Should_Return_Path() {