[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.golacks unit tests and is impossible to test. This is because all the routing registrations and handler initializations are done inside theNewRoutermethod, 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:
HTTPServerstruct, where all services are registered on theHTTPServer: http_server.goHTTPServer. For example: api/user.goHTTPServeris first initialized viawire, and then theregisterRoutesmethod 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
HTTPServeris created usingSetupAPITestServer, and all routes are registered.SetupAPITestServersupports passingopsfunctions (func(hs *HTTPServer)), which helps mock various services that theHTTPServerdepends on.opsfunction.server.NewGetRequest,server.NewPostRequestare 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:
NewRoutermethod, 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.CreateTestContextwith real requests.Refactoring Details:
Serverinterface andBaseServer/ServerImplstructs, placing all handlers under theServerstruct. Because there are many handlers,wirewill be used for automatic injection, separating handler initialization from route registration.wirewill generate injection files force,ee, andsaas.NewTestServermethod will be added, similar to Grafana’sSetupAPITestServer, to create a test server and inject mock handlers via anoptionfunction.NewGetRequest,NewPostRequest, etc., will be added to theTestServer.handler/discussion_test.goandhandler/repo_test.gofiles will be modified as examples of the new test approach.userComponentandmirrorComponent, these components must be injected to test the router.Important Notes:
package handlertopackage handler_test. This is because the router layer sits above the handler layer, and not changing the package will cause a circular reference.BaseServerinapi.goor theServerImplstructure inapi_ce.go/api_ee.go/api_saas.go(modifications like adding or deleting fields), runmake wireagain to regenerate the mocks.