Skip to content

Conversation

@krishankumar01
Copy link
Member

@krishankumar01 krishankumar01 commented Jan 4, 2026

📑 Description

Closes goravel/goravel#841

Introduces a robust testing layer for the HTTP Client, enabling request interception, stateful mocking, and traffic assertions without external network calls.

Key Features

  • Polymorphic Mocking: Fake() accepts simple values (int, string), structured data (map, json), dynamic handlers (func), or stateful sequences.
  • Advanced Pattern Matching: Resolves rules by specificity (Exact Match > Path Pattern > Wildcard).
  • Stateful Sequences: Support for ResponseSequence with repetition (PushStatus(200, 3)), strict exhaustion (error on overflow), and explicit fallbacks (WhenEmpty).
  • Strict Mode: PreventStrayRequests / AllowStrayRequests to enforce hermetic testing boundaries.
  • Traffic Assertions: Full suite of assertion methods: AssertSent, AssertNotSent, AssertSentCount, AssertNothingSent.

Usage Examples

1. Advanced Mocking
Handle various scenarios in a single setup:

facades.Http().Fake(map[string]any{
    // String/JSON Body
    "github.com/users/*": map[string]any{"login": "goravel"},
    
    // Status Code Only
    "google.com/*": 503,
    
    // Dynamic Logic (Access Request Object)
    "api.stripe.com/v1/charges": func(req client.Request) client.Response {
        if req.Header("Authorization") == "" {
            return facades.Http().Response().Status(401)
        }
        return facades.Http().Response().Json(map[string]string{"id": "ch_123"}, 200)
    },

    // Stateful Sequence (Rate Limit Simulation)
    "api.twitter.com/*": facades.Http().Sequence().
                            PushStatus(200).
                            PushStatus(429, 2). // Repeat 429 twice
                            WhenEmpty(facade.Http.Response().Status(200)),
})

2. Assertions
Validate outgoing traffic structure:

// Assert request details
facades.Http().AssertSent(func(req client.Request) bool {
    return req.Url() == "https://api.stripe.com/v1/charges" &&
           req.Input("currency") == "usd" &&
           req.Header("Idempotency-Key") != ""
})

// Assert volume
facades.Http().AssertSentCount(3)
facades.Http().AssertNotSent(func(req client.Request) bool {
    return req.Url() == "https://analytics.service.com"
})

3. Strict Mode Integration
Ensure tests fail on unmocked network calls:

facades.Http().PreventStrayRequests()

// Allows only specific real-world traffic, blocking everything else
facades.Http().AllowStrayRequests([]string{"localhost:*"}) 

Limitations

  • Sequence Exhaustion: ResponseSequence defaults to returning an error (HttpClientHandlerReturnedNil) when exhausted. Use .WhenEmpty() to define persistent behavior.
  • State Isolation: Fakes are bound to the Factory instance. Global singletons require Http.Reset() between tests.

✅ Checks

  • Added test cases for my code

@krishankumar01 krishankumar01 requested a review from a team as a code owner January 4, 2026 20:20
@krishankumar01 krishankumar01 marked this pull request as draft January 4, 2026 20:20
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @krishankumar01, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request, which is the second part of adding HTTP client testing support, focuses on refining the testing infrastructure within the framework. It introduces a new TestingT interface to abstract the standard Go *testing.T, allowing for more flexible and mockable testing scenarios. Key changes include moving the Bind method from the Request contract to the Response contract, providing more descriptive comments for methods across AssertableJSON, Request, and Response interfaces, and updating their concrete implementations. These modifications aim to enhance the clarity, maintainability, and testability of the HTTP client testing utilities.

Highlights

  • Refactored Testing Interfaces: A new TestingT interface has been introduced in contracts/testing/testing.go to abstract the standard Go *testing.T, enhancing testability and flexibility across the testing suite.
  • Improved HTTP Request/Response Contracts: The AssertableJSON interface received clearer method comments and a parameter name change. The Request interface now has comprehensive method comments and its Bind method was removed. The Response interface gained a new Bind method for unmarshalling JSON response bodies and also received detailed method comments.
  • Updated Implementations and Mocks: All relevant testing/http package implementations (assertable_json.go, test_request.go, test_response.go) have been updated to utilize the new testing.TestingT interface. Corresponding mock files were generated or updated to reflect these interface changes, including a new mock for TestingT itself.
  • Enhanced Test Suite Robustness: The assertable_json_test.go now employs a custom MockTestingT to capture assertion failures, making tests more isolated and allowing for controlled verification of error conditions without prematurely failing the test suite.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Jan 4, 2026

Codecov Report

❌ Patch coverage is 89.82630% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.57%. Comparing base (12c365b) to head (50411ac).
⚠️ Report is 10 commits behind head on master.

Files with missing lines Patch % Lines
http/client/request.go 66.66% 10 Missing and 1 partial ⚠️
http/client/factory.go 90.62% 6 Missing and 3 partials ⚠️
http/client/fake_transport.go 80.48% 4 Missing and 4 partials ⚠️
http/client/fake_sequence.go 94.02% 2 Missing and 2 partials ⚠️
http/client/fake_state.go 96.10% 2 Missing and 1 partial ⚠️
testing/http/test_request.go 66.66% 3 Missing ⚠️
testing/http/test_response.go 75.00% 1 Missing and 1 partial ⚠️
testing/test_case.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1339      +/-   ##
==========================================
+ Coverage   70.22%   70.57%   +0.35%     
==========================================
  Files         281      286       +5     
  Lines       16852    17519     +667     
==========================================
+ Hits        11834    12364     +530     
- Misses       4525     4635     +110     
- Partials      493      520      +27     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly improves the HTTP testing support. The introduction of the TestingT interface is a great step towards making the testing helpers more generic and testable. Moving the Bind functionality from Request to Response is a logical API design improvement, making the testing flow more intuitive. The addition of comprehensive comments to the public interfaces and the improved test cases for AssertableJSON are also valuable contributions to the codebase's quality and maintainability. I have a couple of suggestions to further improve the new TestingT interface and fix a typo.

"github.com/goravel/framework/contracts/testing/docker"
)

type TestingT interface {
Copy link
Member Author

Choose a reason for hiding this comment

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

Introducing this so that I can mock the assertions. This helps me test scenarios like AssertableJson, where, if a test case fails and I directly use *testing.T, it prints output to the console. By accepting this interface, I can mock it and then inspect whether the test case correctly triggers a failing assertion.

See:

mockT := &MockTestingT{}

@krishankumar01
Copy link
Member Author

@gemini-code-assist review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive testing framework for the HTTP client, which is a great addition. It allows for faking requests, creating response sequences, and making assertions on sent requests. The implementation is well-structured, introducing concepts like FakeState and FakeTransport to cleanly separate the mocking logic. The changes to the testing interfaces to use TestingT also improve the testability of the framework itself. I've identified a few areas for improvement, mainly concerning error handling and the robustness of the mock pattern matching, to make this new feature even more solid.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces comprehensive testing support for the HTTP client, including faking requests, stubbing responses, and making assertions. The changes are extensive, adding new interfaces, implementations, and tests for fakes, response factories, and response sequences. The API design is clean and follows patterns seen in other popular frameworks. I've identified a couple of areas for improvement related to error handling in the fake factory and API consistency, but overall this is a solid and valuable feature addition.

@krishankumar01 krishankumar01 marked this pull request as ready for review January 11, 2026 10:55
Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Great PR 👍 Left a few questions, but I haven't completed the review yet, will continue tomorrow.

}
}

func (r *FakeResponse) File(path string, status int) client.Response {
Copy link
Contributor

Choose a reason for hiding this comment

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

How about File(status int, path string)?

@hwbrzzl
Copy link
Contributor

hwbrzzl commented Jan 18, 2026

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a robust testing layer for the HTTP client, including request interception, mocking, and assertions. The changes are extensive, adding new interfaces and implementations for faking responses, sequences, and matching rules. The core HTTP client factory and request logic have been updated to integrate these testing capabilities, and the changes are well-supported by new tests.

One key issue was identified: the implementation for handling mock data doesn't fully align with the feature description, specifically for structured data like maps. A fix has been suggested to ensure this works as expected.

Additionally, it's worth noting that there's a breaking change in the testing API: the Bind method has been moved from the test Request to the Response object. This is a good architectural improvement, but it would be beneficial to highlight this in the pull request description to guide users through the migration.

hwbrzzl
hwbrzzl previously approved these changes Jan 19, 2026
Copy link
Contributor

@hwbrzzl hwbrzzl left a comment

Choose a reason for hiding this comment

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

Awesome, LGTM


// Json creates a mock response with a JSON body and "application/json" content type.
Json(obj any, code int) Response
Json(code int, obj any) Response
Copy link
Contributor

@hwbrzzl hwbrzzl Jan 19, 2026

Choose a reason for hiding this comment

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

Suggested change
Json(code int, obj any) Response
Json(status int, obj any) Response

@krishankumar01 krishankumar01 marked this pull request as draft January 19, 2026 10:39
@krishankumar01 krishankumar01 marked this pull request as ready for review January 19, 2026 10:39
@krishankumar01 krishankumar01 marked this pull request as draft January 19, 2026 11:10
@krishankumar01 krishankumar01 marked this pull request as ready for review January 19, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support multiple HTTP clients in the HTTP facade

3 participants