[POC] Unit test Gin router and handler together #281
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem:
The routing registration section in
api.go
lacks unit tests and is impossible to test. This is because all the routing registrations and handler initializations are done inside theNewRouter
method, making it impossible to mock or use dependency injection. The routing registration should also be included in unit tests, as route handling is entirely dependent on string operations and lacks type safety constraints.Industry Approach (Example: Grafana):
Route Registration:
HTTPServer
struct, where all services are registered on theHTTPServer
: http_server.goHTTPServer
. For example: api/user.goHTTPServer
is first initialized viawire
, and then theregisterRoutes
method is called to register routes: api/api.goRoute Testing:
Grafana, a 10-year-old project, uses various methods to test routes. I prefer the following one: api/quota_test.go
HTTPServer
is created usingSetupAPITestServer
, and all routes are registered.SetupAPITestServer
supports passingops
functions (func(hs *HTTPServer)
), which helps mock various services that theHTTPServer
depends on.ops
function.server.NewGetRequest
,server.NewPostRequest
are used to send requests. Since routes have already been registered, the system will automatically match the request’s URL and method to execute the corresponding handler.Current Status of CSGHub Server:
NewRouter
method, making it impossible to mock or use dependency injection.gin.CreateTestContext
, which is unrelated to the route layer and does not include route-matching logic.Refactoring Objective:
Since there is a handler layer, we cannot directly adopt Grafana’s approach. The least intrusive method is to complete route initialization and testing within the handler’s unit tests and replace
gin.CreateTestContext
with real requests.Refactoring Details:
Server
interface andBaseServer/ServerImpl
structs, placing all handlers under theServer
struct. Because there are many handlers,wire
will be used for automatic injection, separating handler initialization from route registration.wire
will generate injection files force
,ee
, andsaas
.NewTestServer
method will be added, similar to Grafana’sSetupAPITestServer
, to create a test server and inject mock handlers via anoption
function.NewGetRequest
,NewPostRequest
, etc., will be added to theTestServer
.handler/discussion_test.go
andhandler/repo_test.go
files will be modified as examples of the new test approach.userComponent
andmirrorComponent
, these components must be injected to test the router.Important Notes:
package handler
topackage handler_test
. This is because the router layer sits above the handler layer, and not changing the package will cause a circular reference.BaseServer
inapi.go
or theServerImpl
structure inapi_ce.go/api_ee.go/api_saas.go
(modifications like adding or deleting fields), runmake wire
again to regenerate the mocks.