From 236153d486dac24b31bc34fce3f9841e931aba66 Mon Sep 17 00:00:00 2001
From: shchoholiev-opflo <s.shchoholiev@opflo.com>
Date: Sat, 14 Oct 2023 02:13:50 +0000
Subject: [PATCH] SA-29 added Unit test for OpenAiService

---
 .devcontainer/devcontainer.json               |  3 +-
 .vscode/settings.json                         |  3 +
 .../GlobalUsings.cs                           |  1 +
 .../OpenAiServiceTests.cs                     | 86 +++++++++++++++++++
 .../ShoppingAssistantApi.UnitTests.csproj     | 31 +++++++
 ShoppingAssistantApi.sln                      |  6 ++
 6 files changed, 129 insertions(+), 1 deletion(-)
 create mode 100644 .vscode/settings.json
 create mode 100644 ShoppingAssistantApi.UnitTests/GlobalUsings.cs
 create mode 100644 ShoppingAssistantApi.UnitTests/OpenAiServiceTests.cs
 create mode 100644 ShoppingAssistantApi.UnitTests/ShoppingAssistantApi.UnitTests.csproj

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 10b6f03..3075303 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -21,7 +21,8 @@
 				"ms-dotnettools.csharp",
 				"patcx.vscode-nuget-gallery",
 				"mhutchie.git-graph",
-				"fernandoescolar.vscode-solution-explorer"
+				"fernandoescolar.vscode-solution-explorer",
+				"formulahendry.dotnet-test-explorer"
 			]
 		}
 	}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..cf3a569
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "editor.formatOnType": true
+}
\ No newline at end of file
diff --git a/ShoppingAssistantApi.UnitTests/GlobalUsings.cs b/ShoppingAssistantApi.UnitTests/GlobalUsings.cs
new file mode 100644
index 0000000..8c927eb
--- /dev/null
+++ b/ShoppingAssistantApi.UnitTests/GlobalUsings.cs
@@ -0,0 +1 @@
+global using Xunit;
\ No newline at end of file
diff --git a/ShoppingAssistantApi.UnitTests/OpenAiServiceTests.cs b/ShoppingAssistantApi.UnitTests/OpenAiServiceTests.cs
new file mode 100644
index 0000000..7ec9de8
--- /dev/null
+++ b/ShoppingAssistantApi.UnitTests/OpenAiServiceTests.cs
@@ -0,0 +1,86 @@
+using System.Net;
+using Moq;
+using Moq.Protected;
+using ShoppingAssistantApi.Application.IServices;
+using ShoppingAssistantApi.Application.Models.OpenAi;
+using ShoppingAssistantApi.Domain.Enums;
+using ShoppingAssistantApi.Infrastructure.Services;
+
+namespace ShoppingAssistantApi.UnitTests;
+
+public class OpenAiServiceTests
+{
+    private readonly IOpenAiService _openAiService;
+
+    private readonly Mock<HttpMessageHandler> _mockHttpMessageHandler;
+
+    private readonly HttpClient _httpClient;
+
+    public OpenAiServiceTests()
+    {
+        // Mock any dependencies
+        _mockHttpMessageHandler = new Mock<HttpMessageHandler>();
+        _httpClient = new HttpClient(_mockHttpMessageHandler.Object);
+        _openAiService = new OpenAiService(_httpClient);
+    }
+
+    [Fact]
+    public async Task GetChatCompletion_ValidChat_ReturnsNewMessage()
+    {
+        // Arrange
+        _mockHttpMessageHandler
+            .Protected()
+            .Setup<Task<HttpResponseMessage>>(
+                "SendAsync",
+                ItExpr.IsAny<HttpRequestMessage>(),
+                ItExpr.IsAny<CancellationToken>()
+            )
+            .ReturnsAsync(new HttpResponseMessage
+            {
+                StatusCode = HttpStatusCode.OK,
+                Content = new StringContent(@"
+                {
+                    ""id"": ""chatcmpl-89OMdgTZXOLAXv7bPUJ4SwrPpS5Md"",
+                    ""object"": ""chat.completion"",
+                    ""created"": 1697249299,
+                    ""model"": ""gpt-3.5-turbo-0613"",
+                    ""choices"": [
+                        {
+                            ""index"": 0,
+                            ""message"": {
+                                ""role"": ""assistant"",
+                                ""content"": ""Hello World!""
+                            },
+                            ""finish_reason"": ""stop""
+                        }
+                    ],
+                    ""usage"": {
+                        ""prompt_tokens"": 10,
+                        ""completion_tokens"": 3,
+                        ""total_tokens"": 13
+                    }
+                }"),
+            });
+            
+        var chat = new ChatCompletionRequest
+        {
+            Messages = new List<OpenAiMessage>
+            {
+                new OpenAiMessage
+                {
+                    Role = OpenAiRole.User,
+                    Content = "Return Hello World!"
+                }
+            }
+        };
+
+        // Act
+        var newMessage = await _openAiService.GetChatCompletion(chat, CancellationToken.None);
+
+        // Assert
+        Assert.NotNull(newMessage);
+        Assert.Equal("Hello, World!", newMessage.Content);
+    }
+
+    // TODO: Add more tests
+}
\ No newline at end of file
diff --git a/ShoppingAssistantApi.UnitTests/ShoppingAssistantApi.UnitTests.csproj b/ShoppingAssistantApi.UnitTests/ShoppingAssistantApi.UnitTests.csproj
new file mode 100644
index 0000000..9274a65
--- /dev/null
+++ b/ShoppingAssistantApi.UnitTests/ShoppingAssistantApi.UnitTests.csproj
@@ -0,0 +1,31 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+
+    <IsPackable>false</IsPackable>
+    <IsTestProject>true</IsTestProject>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
+    <PackageReference Include="Moq" Version="4.20.69" />
+    <PackageReference Include="xunit" Version="2.4.2" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+    <PackageReference Include="coverlet.collector" Version="3.2.0">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\ShoppingAssistantApi.Infrastructure\ShoppingAssistantApi.Infrastructure.csproj" />
+    <ProjectReference Include="..\ShoppingAssistantApi.Application\ShoppingAssistantApi.Application.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/ShoppingAssistantApi.sln b/ShoppingAssistantApi.sln
index fb54417..f2f2788 100644
--- a/ShoppingAssistantApi.sln
+++ b/ShoppingAssistantApi.sln
@@ -15,6 +15,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShoppingAssistantApi.Api",
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoppingAssistantApi.Tests", "ShoppingAssistantApi.Tests\ShoppingAssistantApi.Tests.csproj", "{297B5378-79D7-406C-80A5-151C6B3EA147}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoppingAssistantApi.UnitTests", "ShoppingAssistantApi.UnitTests\ShoppingAssistantApi.UnitTests.csproj", "{B4EFE8F1-89F5-44E4-BD0A-4F63D09C8E6F}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
 		{297B5378-79D7-406C-80A5-151C6B3EA147}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{297B5378-79D7-406C-80A5-151C6B3EA147}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{297B5378-79D7-406C-80A5-151C6B3EA147}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B4EFE8F1-89F5-44E4-BD0A-4F63D09C8E6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B4EFE8F1-89F5-44E4-BD0A-4F63D09C8E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B4EFE8F1-89F5-44E4-BD0A-4F63D09C8E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B4EFE8F1-89F5-44E4-BD0A-4F63D09C8E6F}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE