GraphQL Mocking Strategy
Relevant source files
The following files were used as context for generating this wiki page:
The GraphQL Mocking Strategy provides a robust framework for testing GitHub GraphQL API interactions without making actual network calls. It utilizes a custom mock server that intercepts POST requests to the /graphql endpoint, matching them against predefined query strings and variable sets to return deterministic JSON responses. This strategy is essential for verifying complex data flows in features like Discussions, Issues, and Pull Requests.
Sources: internal/githubv4mock/githubv4mock.go:1-10, pkg/github/discussions_test.go:183-200
Core Components
The mocking system is built around a specialized HTTP client and a set of matchers that simulate the behavior of the GitHub v4 (GraphQL) API.
The Mock Matcher
A Matcher is the fundamental unit of the mocking strategy. It encapsulates the expected GraphQL query (as a minified string), the expected variables, and the desired GQLResponse.
- Query Matching: The system expects an exact string match for queries. Since queries are often generated from Go structs with
graphqltags, the library includes utilities to minify and normalize these strings. - Variable Validation: Variables are considered equal if they approximate to the same type, allowing the system to handle cases where type information is lost during JSON marshaling/unmarshaling in the HTTP handler.
Sources: internal/githubv4mock/githubv4mock.go:13-20, internal/githubv4mock/githubv4mock.go:111-135
Mocked HTTP Client
The NewMockedHTTPClient function initializes an http.Client configured with a localRoundTripper. This client registers a handler for /graphql POST requests. When a request is received, it parses the body, identifies the query and variables, and searches for a registered Matcher.
Sources: internal/githubv4mock/githubv4mock.go:104-111, internal/githubv4mock/local_round_tripper.go:42-47
Component Relationship Diagram
The diagram shows how the localRoundTripper intercepts client requests and routes them through a matching logic that utilizes predefined Matcher data structures.
Sources: internal/githubv4mock/githubv4mock.go:104-145, internal/githubv4mock/local_round_tripper.go:37-47
Implementation Logic
Query and Mutation Construction
The system provides helper functions to convert Go structs or raw strings into GraphQL-compatible formats. This is crucial because the githubv4 library uses reflection to derive queries from types.
| Function | Purpose | Logic |
|---|---|---|
NewQueryMatcher | Creates a matcher for queries | Converts a struct to a minified string using constructQuery if a string isn't provided. |
NewMutationMatcher | Creates a matcher for mutations | Specifically handles the input variable common in mutations; converts input structs to maps for equality checks. |
constructQuery | String generation | Appends query() arguments and recursively builds the field selection set. |
Sources: internal/githubv4mock/githubv4mock.go:21-30, internal/githubv4mock/githubv4mock.go:43-57, internal/githubv4mock/query.go:45-53
Handling Responses
The strategy distinguishes between successful data retrieval and API-level errors.
- DataResponse: Wraps a
map[string]anyinto thedatafield of a standard GraphQL JSON response. - ErrorResponse: Simulates API failures by populating the
errorsarray in the response body. Even when errors are returned, the mock server typically returns a200 OKstatus code, mimicking real GraphQL API behavior where errors are part of the payload.
Sources: internal/githubv4mock/githubv4mock.go:72-90
Sequence of a Mocked Request
This sequence demonstrates the interception of the standard HTTP flow to provide mocked data back to the GraphQL client.
Sources: internal/githubv4mock/githubv4mock.go:114-148, internal/githubv4mock/local_round_tripper.go:42-47
Practical Examples in Testing
Discussions Testing
In discussions_test.go, the mocking strategy is used to test complex filtering and ordering. For instance, testing ListDiscussions involves matching different query strings depending on whether a categoryId or orderBy parameter is provided.
Sources: pkg/github/discussions_test.go:202-235
Pull Request Draft Transitions
Testing the transition of a Pull Request from draft to ready involves matching a query (to get the PR ID) and then a mutation (markPullRequestReadyForReview).
// Example of a mutation matcher for PR state change
githubv4mock.NewMutationMatcher(
struct {
MarkPullRequestReadyForReview struct {
PullRequest struct {
ID githubv4.ID
IsDraft githubv4.Boolean
}
} `graphql:"markPullRequestReadyForReview(input: $input)"`
}{},
githubv4.MarkPullRequestReadyForReviewInput{
PullRequestID: "PR_kwDOA0xdyM50BPaO",
},
nil,
githubv4mock.DataResponse(map[string]any{...}),
)
Sources: pkg/github/pullrequests_test.go:417-438
Conclusion
The GraphQL Mocking Strategy is a central pillar of the project's testing infrastructure. By providing a deterministic, minified query matching engine and a local HTTP interceptor, it allows developers to verify complex GitHub integration logic—including repository operations, issue management, and pull request workflows—with high confidence and without external dependencies.
Sources: internal/githubv4mock/githubv4mock.go:1-10, pkg/github/issues_test.go:1115-1150