tests: cover null responses
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using AnthropicClient.Json;
|
||||
using AnthropicClient.Models;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AnthropicClient.Tests.Files;
|
||||
using AnthropicClient.Tests.Unit;
|
||||
|
||||
namespace AnthropicClient.Tests.Integration;
|
||||
|
||||
@@ -35,6 +34,51 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
actualErrorType.Should().Be(errorType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateMessageAsync_WhenCalledRequestFailsAndCanNotDeserializeError_ItShouldReturnUnknownError()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenCreateMessageRequest()
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new MessageRequest(
|
||||
model: AnthropicModels.Claude3Haiku,
|
||||
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
|
||||
);
|
||||
|
||||
var result = await Client.CreateMessageAsync(request);
|
||||
|
||||
result.IsSuccess.Should().BeFalse();
|
||||
result.Error.Should().BeOfType<AnthropicError>();
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateMessageAsync_WhenCalledRequestSucceedsAndCanNotDeserializeResponse_ItShouldReturnEmptyResponse()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenCreateMessageRequest()
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new MessageRequest(
|
||||
model: AnthropicModels.Claude3Haiku,
|
||||
messages: [new(MessageRole.User, [new TextContent("Hello!")])]
|
||||
);
|
||||
|
||||
var result = await Client.CreateMessageAsync(request);
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().BeEquivalentTo(new MessageResponse());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateMessageAsync_WhenCalledAndMessageCreatedWithTextContent_ItShouldReturnMessage()
|
||||
{
|
||||
@@ -363,6 +407,34 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateMessageAsync_WhenCalledMessageIsStreamedRequestFailsAndCanNotDeserializeError_ItShouldReturnUnknownErrorEvent()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenCreateStreamMessageRequest()
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new StreamMessageRequest(
|
||||
model: AnthropicModels.Claude35Sonnet,
|
||||
messages: [
|
||||
new(MessageRole.User, [new TextContent("Hello!")]),
|
||||
new(MessageRole.User, [new TextContent("Hello!")])
|
||||
]
|
||||
);
|
||||
|
||||
var result = Client.CreateMessageAsync(request);
|
||||
var events = await result.ToListAsync();
|
||||
|
||||
events.Should().HaveCount(1);
|
||||
events[0].Type.Should().Be(EventType.Error);
|
||||
events[0].Data.Should().BeOfType<ErrorEventData>();
|
||||
events[0].Data.Should().BeEquivalentTo(new ErrorEventData(new ApiError()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateMessageAsync_WhenCalledAndMessageCreatedWithDocumentContent_ItShouldReturnMessage()
|
||||
{
|
||||
@@ -489,7 +561,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new CountMessageTokensRequest(
|
||||
@@ -507,6 +579,31 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CountMessageTokensAsync_WhenCalledAndResponseCanNotBeDeserialized_ItShouldReturnEmptyResponse()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenCountMessageTokensRequest()
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new CountMessageTokensRequest(
|
||||
model: AnthropicModels.Claude35Sonnet,
|
||||
messages: [
|
||||
new(MessageRole.User, [new TextContent("Hello!")]),
|
||||
]
|
||||
);
|
||||
|
||||
var result = await Client.CountMessageTokensAsync(request);
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().BeOfType<TokenCountResponse>();
|
||||
result.Value.InputTokens.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ListModelsAsync_WhenCalledWithPagingRequestUsingDefaultValues_ItShouldReturnListOfModels()
|
||||
{
|
||||
@@ -656,7 +753,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.ListModelsAsync();
|
||||
@@ -666,6 +763,27 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ListModelAsync_WhenCalledRequestSucceedsAndCanNotDeserializeResponse_ItShouldReturnEmptyPage()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenListModelsRequest()
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.ListModelsAsync();
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().BeOfType<Page<AnthropicModel>>();
|
||||
result.Value.HasMore.Should().BeFalse();
|
||||
result.Value.FirstId.Should().BeEmpty();
|
||||
result.Value.LastId.Should().BeEmpty();
|
||||
result.Value.Data.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ListAllModelsAsync_WhenCalled_ItShouldReturnAllModels()
|
||||
{
|
||||
@@ -803,7 +921,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var responses = Client.ListAllModelsAsync();
|
||||
@@ -889,6 +1007,35 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
count.Should().Be(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ListAllModelsAsync_WhenFirstPageSucceedsButResponseCanNotBeDeserialized_ItShouldReturnEmptyPage()
|
||||
{
|
||||
_mockHttpMessageHandler
|
||||
.WhenListModelsRequest()
|
||||
.WithExactQueryString(new Dictionary<string, string>
|
||||
{
|
||||
{ "limit", "20" },
|
||||
})
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var responses = Client.ListAllModelsAsync();
|
||||
var count = 0;
|
||||
|
||||
await foreach (var page in responses)
|
||||
{
|
||||
count++;
|
||||
page.IsSuccess.Should().BeTrue();
|
||||
page.Value.Should().BeOfType<Page<AnthropicModel>>();
|
||||
page.Value.Data.Should().BeEmpty();
|
||||
}
|
||||
|
||||
count.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetModelAsync_WhenCalled_ItShouldReturnModel()
|
||||
{
|
||||
@@ -953,7 +1100,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetModelAsync(modelId);
|
||||
@@ -973,7 +1120,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetModelAsync(modelId);
|
||||
@@ -1070,7 +1217,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new MessageBatchRequest([new("custom_id", new())]);
|
||||
@@ -1090,7 +1237,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var request = new MessageBatchRequest([new("custom_id", new())]);
|
||||
@@ -1193,7 +1340,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetMessageBatchAsync(batchId);
|
||||
@@ -1213,7 +1360,7 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/json",
|
||||
@"{}"
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetMessageBatchAsync(batchId);
|
||||
@@ -1247,4 +1394,76 @@ public class AnthropicApiClientTests : IntegrationTest
|
||||
|
||||
actualResults.Should().BeEquivalentTo(expectedResults);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetMessageBatchResultsAsync_WhenCalledSuccessfulAndResultCanNotBeDeserialized_ItShouldReturnEmptyResults()
|
||||
{
|
||||
var batchId = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF";
|
||||
var expectedResults = new List<MessageBatchResultItem>()
|
||||
{
|
||||
new(),
|
||||
};
|
||||
|
||||
_mockHttpMessageHandler
|
||||
.WhenGetMessageBatchResultsRequest(batchId)
|
||||
.Respond(
|
||||
HttpStatusCode.OK,
|
||||
"application/x-jsonl",
|
||||
"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetMessageBatchResultsAsync(batchId);
|
||||
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
|
||||
var actualResults = await result.Value.ToListAsync();
|
||||
|
||||
actualResults.Should().BeEquivalentTo(expectedResults);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetMessageBatchResultsAsync_WhenCalledAndRequestFails_ItShouldReturnError()
|
||||
{
|
||||
var batchId = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF";
|
||||
|
||||
_mockHttpMessageHandler
|
||||
.WhenGetMessageBatchResultsRequest(batchId)
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"{
|
||||
""type"": ""error"",
|
||||
""error"": {
|
||||
""type"": ""invalid_request_error"",
|
||||
""message"": ""messages: roles must alternate between user and assistant, but found multiple user roles in a row""
|
||||
}
|
||||
}"
|
||||
);
|
||||
|
||||
var result = await Client.GetMessageBatchResultsAsync(batchId);
|
||||
|
||||
result.IsSuccess.Should().BeFalse();
|
||||
result.Error.Should().BeOfType<AnthropicError>();
|
||||
result.Error.Error.Should().BeOfType<InvalidRequestError>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetMessageBatchResultsAsync_WhenCalledRequestFailsAndCanNotDeserializeError_ItShouldReturnUnknownError()
|
||||
{
|
||||
var batchId = "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF";
|
||||
|
||||
_mockHttpMessageHandler
|
||||
.WhenGetMessageBatchResultsRequest(batchId)
|
||||
.Respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
"application/json",
|
||||
@"null"
|
||||
);
|
||||
|
||||
var result = await Client.GetMessageBatchResultsAsync(batchId);
|
||||
|
||||
result.IsSuccess.Should().BeFalse();
|
||||
result.Error.Should().BeOfType<AnthropicError>();
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace AnthropicClient.Tests.Unit.Models;
|
||||
|
||||
public class CanceledMessageBatchResultTests : SerializationTest
|
||||
{
|
||||
private const string SampleJson = @"{
|
||||
""type"": ""canceled""
|
||||
}";
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WhenCalled_ItShouldReturnAnInstanceWithPropertiesSet()
|
||||
{
|
||||
var result = new CanceledMessageBatchResult();
|
||||
|
||||
result.Type.Should().Be(MessageBatchResultType.Canceled);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||
{
|
||||
var result = new CanceledMessageBatchResult();
|
||||
|
||||
var json = Serialize(result);
|
||||
|
||||
JsonAssert.Equal(SampleJson, json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedProperties()
|
||||
{
|
||||
var result = Deserialize<CanceledMessageBatchResult>(SampleJson);
|
||||
|
||||
result!.Type.Should().Be(MessageBatchResultType.Canceled);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
namespace AnthropicClient.Tests.Unit.Models;
|
||||
|
||||
public class ErroredMessageBatchResultTests : SerializationTest
|
||||
{
|
||||
private const string SampleJson = @"{
|
||||
""type"": ""errored"",
|
||||
""error"": {
|
||||
""type"": ""error"",
|
||||
""error"": {
|
||||
""type"": ""api_error"",
|
||||
""message"": ""An error occurred.""
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WhenCalled_ItShouldReturnAnInstanceWithPropertiesSet()
|
||||
{
|
||||
var result = new ErroredMessageBatchResult();
|
||||
|
||||
result.Type.Should().Be(MessageBatchResultType.Errored);
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
result.Error.Error.Message.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||
{
|
||||
var result = new ErroredMessageBatchResult
|
||||
{
|
||||
Error = new(new ApiError("An error occurred."))
|
||||
};
|
||||
|
||||
var json = Serialize(result);
|
||||
|
||||
JsonAssert.Equal(SampleJson, json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedProperties()
|
||||
{
|
||||
var result = Deserialize<ErroredMessageBatchResult>(SampleJson);
|
||||
|
||||
result!.Type.Should().Be(MessageBatchResultType.Errored);
|
||||
result.Error.Error.Should().BeOfType<ApiError>();
|
||||
result.Error.Error.Message.Should().Be("An error occurred.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace AnthropicClient.Tests.Unit.Models;
|
||||
|
||||
public class ExpiredMessageBatchResultTests : SerializationTest
|
||||
{
|
||||
private const string SampleJson = @"{
|
||||
""type"": ""expired""
|
||||
}";
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WhenCalled_ItShouldReturnAnInstanceWithPropertiesSet()
|
||||
{
|
||||
var result = new ExpiredMessageBatchResult();
|
||||
|
||||
result.Type.Should().Be(MessageBatchResultType.Expired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||
{
|
||||
var result = new ExpiredMessageBatchResult();
|
||||
|
||||
var json = Serialize(result);
|
||||
|
||||
JsonAssert.Equal(SampleJson, json);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonDeserialization_WhenDeserialized_ItShouldHaveExpectedProperties()
|
||||
{
|
||||
var result = Deserialize<ExpiredMessageBatchResult>(SampleJson);
|
||||
|
||||
result!.Type.Should().Be(MessageBatchResultType.Expired);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace AnthropicClient.Tests.Unit.Models;
|
||||
|
||||
public class MessageBatchResultTests : SerializationTest
|
||||
{
|
||||
[Fact]
|
||||
public void JsonDeserialization_WhenHasUnknownType_ItShouldThrowException()
|
||||
{
|
||||
var json = @"{""type"":""unknown""}";
|
||||
|
||||
var action = () => Deserialize<MessageBatchResult>(json);
|
||||
|
||||
action.Should().Throw<JsonException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonSerialization_WhenSerialized_ItShouldHaveExpectedShape()
|
||||
{
|
||||
var expectedJson = @"{""type"":""expired""}";
|
||||
var messageBatchResult = new ExpiredMessageBatchResult();
|
||||
|
||||
var json = Serialize<MessageBatchResult>(messageBatchResult);
|
||||
|
||||
JsonAssert.Equal(expectedJson, json);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace AnthropicClient.Tests.Unit.Models;
|
||||
|
||||
public class ToolCallTests : SerializationTest
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using AnthropicClient.Json;
|
||||
|
||||
namespace AnthropicClient.Tests.Unit;
|
||||
|
||||
public class SerializationTest
|
||||
|
||||
Reference in New Issue
Block a user