From ebae27077ebaf4b1bd867560b589d62fe0119449 Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Mon, 1 Jul 2024 23:59:24 -0500 Subject: [PATCH] tests: work on adding integration tests --- .../AnthropicClient.Tests.csproj | 1 + .../Integration/AnthropicApiClientTests.cs | 34 ++++++ .../Integration/ErrorTestData.cs | 100 ++++++++++++++++++ .../Integration/IntegrationTest.cs | 40 +++++++ .../Unit/Utils/JsonSchemaGeneratorTestData.cs | 1 - tests/AnthropicClient.Tests/Usings.cs | 6 +- 6 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs create mode 100644 tests/AnthropicClient.Tests/Integration/ErrorTestData.cs create mode 100644 tests/AnthropicClient.Tests/Integration/IntegrationTest.cs diff --git a/tests/AnthropicClient.Tests/AnthropicClient.Tests.csproj b/tests/AnthropicClient.Tests/AnthropicClient.Tests.csproj index 491e4db..f21321f 100644 --- a/tests/AnthropicClient.Tests/AnthropicClient.Tests.csproj +++ b/tests/AnthropicClient.Tests/AnthropicClient.Tests.csproj @@ -14,6 +14,7 @@ + diff --git a/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs new file mode 100644 index 0000000..d073564 --- /dev/null +++ b/tests/AnthropicClient.Tests/Integration/AnthropicApiClientTests.cs @@ -0,0 +1,34 @@ +namespace AnthropicClient.Tests.Integration; + +public class AnthropicApiClientTests : IntegrationTest +{ + [Theory] + [ClassData(typeof(ErrorTestData))] + public async Task CreateChatMessageAsync_WhenCalledAndErrorReturned_ItShouldHandleError( + HttpStatusCode statusCode, + string content, + Type errorType + ) + { + _mockHttpMessageHandler + .WhenCreateMessageRequest() + .Respond( + statusCode, + "application/json", + content + ); + + var request = new ChatMessageRequest( + model: AnthropicModels.Claude3Haiku, + messages: [new(MessageRole.User, [new TextContent("Hello!")])] + ); + + var result = await Client.CreateChatMessageAsync(request); + + result.IsSuccess.Should().BeFalse(); + result.Error.Should().BeOfType(); + + var actualErrorType = result.Error.Error!.GetType(); + actualErrorType.Should().Be(errorType); + } +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Integration/ErrorTestData.cs b/tests/AnthropicClient.Tests/Integration/ErrorTestData.cs new file mode 100644 index 0000000..ed20c58 --- /dev/null +++ b/tests/AnthropicClient.Tests/Integration/ErrorTestData.cs @@ -0,0 +1,100 @@ +namespace AnthropicClient.Tests.Integration; + +public class ErrorTestData : IEnumerable +{ + public IEnumerator GetEnumerator() + { + yield return new object[] + { + HttpStatusCode.BadRequest, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""invalid_request_error"", + ""message"": ""Invalid request."" + } + }", + typeof(InvalidRequestError) + }; + + yield return new object[] + { + HttpStatusCode.Unauthorized, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""authentication_error"", + ""message"": ""Authentication error."" + } + }", + typeof(AuthenticationError) + }; + + yield return new object[] + { + HttpStatusCode.Forbidden, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""permission_error"", + ""message"": ""Permission error."" + } + }", + typeof(PermissionError) + }; + + yield return new object[] + { + HttpStatusCode.NotFound, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""not_found_error"", + ""message"": ""Not found error."" + } + }", + typeof(NotFoundError) + }; + + yield return new object[] + { + HttpStatusCode.TooManyRequests, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""rate_limit_error"", + ""message"": ""Rate limit error."" + } + }", + typeof(RateLimitError) + }; + + yield return new object[] + { + HttpStatusCode.InternalServerError, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""api_error"", + ""message"": ""Internal server error."" + } + }", + typeof(ApiError) + }; + + yield return new object[] + { + (HttpStatusCode)529, + @"{ + ""type"": ""error"", + ""error"": { + ""type"": ""overloaded_error"", + ""message"": ""Overloaded error."" + } + }", + typeof(OverloadedError) + }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Integration/IntegrationTest.cs b/tests/AnthropicClient.Tests/Integration/IntegrationTest.cs new file mode 100644 index 0000000..857fb0f --- /dev/null +++ b/tests/AnthropicClient.Tests/Integration/IntegrationTest.cs @@ -0,0 +1,40 @@ +namespace AnthropicClient.Tests.Integration; + +public class IntegrationTest +{ + protected readonly MockHttpMessageHandler _mockHttpMessageHandler = new(); + protected AnthropicApiClient Client => CreateClient(); + + private AnthropicApiClient CreateClient() + { + return new AnthropicApiClient("test-key", _mockHttpMessageHandler.ToHttpClient()); + } +} + +public static class MockHttpMessageHandlerExtensions +{ + private static MockedRequest SetupBaseRequest(this MockHttpMessageHandler mockHttpMessageHandler) + { + return mockHttpMessageHandler + .When(HttpMethod.Post, "https://api.anthropic.com/v1/messages") + .WithHeaders(new Dictionary + { + { "anthropic-version", "2023-06-01" }, + { "x-api-key", "test-key" } + }); + } + + public static MockedRequest WhenCreateMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler) + { + return mockHttpMessageHandler + .SetupBaseRequest() + .WithJsonContent(r => r.Stream == false); + } + + public static MockedRequest WhenCreateStreamMessageRequest(this MockHttpMessageHandler mockHttpMessageHandler) + { + return mockHttpMessageHandler + .SetupBaseRequest() + .WithJsonContent(r => r.Stream == true); + } +} \ No newline at end of file diff --git a/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTestData.cs b/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTestData.cs index 906d68c..b7abfce 100644 --- a/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTestData.cs +++ b/tests/AnthropicClient.Tests/Unit/Utils/JsonSchemaGeneratorTestData.cs @@ -1,4 +1,3 @@ -using System.Collections; using System.Text.Json.Nodes; namespace AnthropicClient.Tests.Unit.Utils; diff --git a/tests/AnthropicClient.Tests/Usings.cs b/tests/AnthropicClient.Tests/Usings.cs index 4b78fc5..27ef28a 100644 --- a/tests/AnthropicClient.Tests/Usings.cs +++ b/tests/AnthropicClient.Tests/Usings.cs @@ -6,4 +6,8 @@ global using AnthropicClient.Utils; global using FluentAssertions; -global using Microsoft.Extensions.Configuration; \ No newline at end of file +global using Microsoft.Extensions.Configuration; + +global using RichardSzalay.MockHttp; +global using System.Net; +global using System.Collections; \ No newline at end of file