Skip to content

Add tests for ErrorResponse without JSON#108

Merged
twogood merged 3 commits intomainfrom
ErrorResponse-tests
Oct 19, 2025
Merged

Add tests for ErrorResponse without JSON#108
twogood merged 3 commits intomainfrom
ErrorResponse-tests

Conversation

@twogood
Copy link
Owner

@twogood twogood commented Oct 19, 2025

Summary by CodeRabbit

  • Tests
    • Added end-to-end tests validating handling of text/plain error responses, covering both default string payloads and custom error payload types; verifies error extraction and exception messages.
    • Added tests for XML error responses that validate parsing of XML error payloads, status-code behavior, and retrieval of structured error data.

@twogood twogood self-assigned this Oct 19, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 19, 2025

Walkthrough

Adds two new test classes that validate RestClient handling of error responses: one for text/plain payloads (including a custom error type) and one for XML payloads. Each test file defines test service interfaces and error-response types and uses a mocked HTTP pipeline.

Changes

Cohort / File(s) Summary
Text/plain error response tests
Activout.RestClient.Test/ErrorResponseTextPlainTest.cs
New test class ErrorResponseTextPlainTest with two tests for 400 Bad Request handling of text/plain error bodies. Adds ITestService and ITestServiceWithCustomError interfaces, CreateTestService helpers, and CustomErrorMessage record.
XML error response tests
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs
New test class ErrorResponseXmlTest with a test for 400 Bad Request handling of XML error bodies. Adds ITestService interface and XmlErrorResponse class with XML serialization attributes (code, message).

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test (xUnit)
    participant RC as RestClientFactory / RestClient
    participant Mock as Mock HTTP Handler

    Note over Test,RC: Setup - create RestClient with Mock handler
    Test->>RC: Invoke GetResource / GetResourceAsync
    RC->>Mock: Send HTTP request
    Mock-->>RC: 400 Bad Request with error body (text/plain or XML)
    RC--xTest: Throw RestClientException (StatusCode=400, ErrorResponse present)
    Test->>RC: exception.GetErrorResponse<T>()
    RC-->>Test: Parsed error payload (string / CustomErrorMessage / XmlErrorResponse)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped to tests with keen delight,

caught plain text errors in the night,
parsed XML whispers, tidy and bright,
messages echoed — all set-right. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "Add tests for ErrorResponse without JSON" accurately and clearly describes the main objective of the changeset. The PR introduces two new test files: one for text/plain error responses (ErrorResponseTextPlainTest.cs) and one for XML error responses (ErrorResponseXmlTest.cs). The title correctly captures that these tests expand ErrorResponse handling coverage to non-JSON formats. The phrasing is concise and specific enough that a reviewer scanning the commit history would understand the primary contribution without ambiguity or vagueness.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ErrorResponse-tests

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 76d05e6 and 16fc589.

📒 Files selected for processing (2)
  • Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (1 hunks)
  • Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.cs: Use [] list syntax for collections
Use file-scoped namespaces
Use primary constructors wherever possible
Use records for data transfer objects (DTOs) and immutable data structures
Use var for local variable declarations when possible
Use expression-bodied members for simple methods and properties
Use pattern matching for type checks and deconstruction
Use using statements for resource management
Use async and await for asynchronous programming
Never include "Async" in method names
Only include comments that explain why something is done, not what is done

Files:

  • Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs
  • Activout.RestClient.Test/ErrorResponseTextPlainTest.cs
🧬 Code graph analysis (2)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (2)
Activout.RestClient/Services.cs (2)
  • IRestClientFactory (21-30)
  • Services (9-36)
Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (3)
  • ITestService (19-26)
  • Fact (37-56)
  • Fact (58-77)
Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (1)
Activout.RestClient/Services.cs (2)
  • IRestClientFactory (21-30)
  • Services (9-36)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (5)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (2)

27-54: LGTM! Well-structured error response test.

The test follows the AAA pattern, properly mocks the HTTP response, and comprehensively validates the XML error response deserialization. The assertions verify status code, error response type, and payload content correctly.


9-72: Previous 'Async' suffix issues have been resolved.

The code now correctly omits "Async" from method names (line 61: GetResource()) and follows all C# coding guidelines: file-scoped namespace, primary constructor, proper var usage, and clean test structure.

Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (3)

95-95: Excellent use of record for the error DTO!

CustomErrorMessage correctly uses a record with a primary constructor, following the guideline to "use records for data transfer objects (DTOs) and immutable data structures."


37-77: LGTM! Comprehensive text/plain error response tests.

Both test methods follow best practices:

  • AAA pattern for clarity
  • Proper HTTP mocking
  • Thorough assertions validating error response type and content
  • Coverage of both string and custom error types

11-96: Previous 'Async' suffix issues have been resolved.

All method names now correctly omit "Async" (lines 38, 48, 59, 69, 84, 92). The code follows C# guidelines throughout: file-scoped namespace, primary constructors, proper var usage, and excellent use of records for DTOs.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (9)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (6)

28-29: Drop 'Async' suffix in test method name (coding guidelines)

Rename to comply with “Never include 'Async' in method names.”

-    public async Task TestErrorResponse_Xml_BadRequest_Async()
+    public async Task TestErrorResponse_Xml_BadRequest()

17-25: Make CreateTestService expression-bodied

Simplifies boilerplate and matches the guideline.

-    private ITestService CreateTestService()
-    {
-        return _restClientFactory.CreateBuilder()
-            .WithXml()
-            .With(_loggerFactory.CreateLogger<ErrorResponseXmlTest>())
-            .With(_mockHttp.ToHttpClient())
-            .BaseUri(BaseUri)
-            .Build<ITestService>();
-    }
+    private ITestService CreateTestService() =>
+        _restClientFactory.CreateBuilder()
+            .WithXml()
+            .With(_loggerFactory.CreateLogger<ErrorResponseXmlTest>())
+            .With(_mockHttp.ToHttpClient())
+            .BaseUri(BaseUri)
+            .Build<ITestService>();

64-72: Prefer a record for the XML DTO

Use a record class per guideline; keep set accessors for XmlSerializer.

-    [XmlRoot("error")]
-    public class XmlErrorResponse
+    [XmlRoot("error")]
+    public record class XmlErrorResponse
     {
         [XmlElement("code")]
         public int Code { get; set; }

         [XmlElement("message")]
         public string Message { get; set; } = "";
     }

47-54: Also assert exception.Message for parity with text/plain test

Keep assertions consistent across MIME types.

         var errorResponse = exception.GetErrorResponse<XmlErrorResponse>();
         Assert.Equal(400, errorResponse.Code);
         Assert.Equal("Invalid request parameter", errorResponse.Message);
+        Assert.Equal("Invalid request parameter", exception.Message);

40-40: Prefer 'application/xml' over 'text/xml'

Use the modern, standard media type.

-            .Respond(HttpStatusCode.BadRequest, "text/xml", errorXml);
+            .Respond(HttpStatusCode.BadRequest, "application/xml", errorXml);

30-31: Remove AAA comments

Guideline: only “why” comments. These narrate “what”.

Also applies to: 44-45, 47-48

Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (3)

19-26: Use expression-bodied builders

Shorter and idiomatic for simple factory helpers.

-    private ITestService CreateTestService()
-    {
-        return _restClientFactory.CreateBuilder()
-            .With(_loggerFactory.CreateLogger<ErrorResponseTextPlainTest>())
-            .With(_mockHttp.ToHttpClient())
-            .BaseUri(BaseUri)
-            .Build<ITestService>();
-    }
+    private ITestService CreateTestService() =>
+        _restClientFactory.CreateBuilder()
+            .With(_loggerFactory.CreateLogger<ErrorResponseTextPlainTest>())
+            .With(_mockHttp.ToHttpClient())
+            .BaseUri(BaseUri)
+            .Build<ITestService>();
@@
-    private ITestServiceWithCustomError CreateTestServiceWithCustomError()
-    {
-        return _restClientFactory.CreateBuilder()
-            .With(_loggerFactory.CreateLogger<ErrorResponseTextPlainTest>())
-            .With(_mockHttp.ToHttpClient())
-            .BaseUri(BaseUri)
-            .Build<ITestServiceWithCustomError>();
-    }
+    private ITestServiceWithCustomError CreateTestServiceWithCustomError() =>
+        _restClientFactory.CreateBuilder()
+            .With(_loggerFactory.CreateLogger<ErrorResponseTextPlainTest>())
+            .With(_mockHttp.ToHttpClient())
+            .BaseUri(BaseUri)
+            .Build<ITestServiceWithCustomError>();

Also applies to: 28-35


71-77: Assert exception.Message in custom-error test as well

Parities with the first test and validates propagated message.

         var customError = exception.GetErrorResponse<CustomErrorMessage>();
         Assert.Equal("Invalid request parameter", customError.Message);
+        Assert.Equal("Invalid request parameter", exception.Message);

41-41: Remove AAA comments

Keep only “why” comments per guideline.

Also applies to: 47-47, 50-50, 62-62, 68-68, 71-71

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbcf780 and 76d05e6.

📒 Files selected for processing (2)
  • Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (1 hunks)
  • Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.cs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.cs: Use [] list syntax for collections
Use file-scoped namespaces
Use primary constructors wherever possible
Use records for data transfer objects (DTOs) and immutable data structures
Use var for local variable declarations when possible
Use expression-bodied members for simple methods and properties
Use pattern matching for type checks and deconstruction
Use using statements for resource management
Use async and await for asynchronous programming
Never include "Async" in method names
Only include comments that explain why something is done, not what is done

Files:

  • Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs
  • Activout.RestClient.Test/ErrorResponseTextPlainTest.cs
🧬 Code graph analysis (2)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (2)
Activout.RestClient/Services.cs (2)
  • IRestClientFactory (21-30)
  • Services (9-36)
Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (5)
  • ITestService (19-26)
  • Fact (37-56)
  • Fact (58-77)
  • Get (83-84)
  • Get (91-92)
Activout.RestClient.Test/ErrorResponseTextPlainTest.cs (2)
Activout.RestClient/Services.cs (2)
  • IRestClientFactory (21-30)
  • Services (9-36)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (3)
  • ITestService (17-25)
  • Fact (27-54)
  • Get (60-61)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (1)
Activout.RestClient.Xml.Test/ErrorResponseXmlTest.cs (1)

1-6: No action required

Global using for Xunit is present at Activout.RestClient.Xml.Test/GlobalUsings.cs, so the [Fact] attribute is properly available.

@twogood twogood merged commit 1913dfe into main Oct 19, 2025
9 checks passed
@twogood twogood deleted the ErrorResponse-tests branch October 19, 2025 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant