Ich glaube nicht, dass es eine einzige Antwort für diese Frage gibt, aber ich werde meinen Ansatz teilen, wie ich derzeit Dependency Injection on Go mit Go-Gin mache (sollte aber fast das gleiche mit allen anderen sein Router).
Aus geschäftlicher Sicht habe ich eine Struktur, die alle Zugriff auf meine Dienste, die für Geschäftsregeln/Verarbeitung verantwortlich sind, umschließt.
// WchyContext is an application-wide context
type WchyContext struct {
Health services.HealthCheckService
Tenant services.TenantService
... whatever
}
Meine Dienste sind dann nur Schnittstellen.
// HealthCheckService is a simple general purpose health check service
type HealthCheckService interface {
IsDatabaseOnline() bool
}
Welche mulitple Implementierungen haben, wie MockedHealthCheck
, PostgresHealthCheck
, PostgresTenantService
und so weiter.
als Mein Router auf einem WchyContext abhängt, das der Code wie folgt aussieht:
func GetMainEngine(ctx context.WchyContext) *gin.Engine {
router := gin.New()
router.Use(gin.Logger())
router.GET("/status", Status(ctx))
router.GET("/tenants/:domain", TenantByDomain(ctx))
return router
}`
Status
und TenantByDomain
wirkt wie eine Handler-Fabrik, die alle es tut, sind einen neuen Handler auf gegebenen Kontext schaffen basierten, wie dies:
type statusHandler struct {
ctx context.WchyContext
}
// Status creates a new Status HTTP handler
func Status(ctx context.WchyContext) gin.HandlerFunc {
return statusHandler{ctx: ctx}.get()
}
func (h statusHandler) get() gin.HandlerFunc {
return func(c *gin.Context) {
c.JSON(200, gin.H{
"healthy": gin.H{
"database": h.ctx.Health.IsDatabaseOnline(),
},
"now": time.Now().Format("2006.01.02.150405"),
})
}
}
Wie Sie sehen können, meine Gesundheits-Check-Handler kümmert sich nicht um die konkrete Umsetzung meiner Leistungen, ich kann es nur verwenden, was in der ctx.
ist 210
Der letzte Teil hängt von der aktuellen Ausführungsumgebung ab. Während automatisierten Tests erstelle ich eine neue WchyContext
mit verspottet/stubbed Dienste und es GetMainEngine senden, wie folgt aus:
ctx := context.WchyContext{
Health: &services.InMemoryHealthCheckService{Status: false},
Tenant: &services.InMemoryTenantService{Tenants: []*models.Tenant{
&models.Tenant{ID: 1, Name: "Orange Inc.", Domain: "orange"},
&models.Tenant{ID: 2, Name: "The Triathlon Shop", Domain: "trishop"},
}}
}
router := handlers.GetMainEngine(ctx)
request, _ := http.NewRequest(method, url, nil)
response := httptest.NewRecorder()
router.ServeHTTP(response, request)
... check if response matches what you expect from your handler
Und wenn Sie Setup es wirklich hören auf einen HTTP-Port, die Verkabelung bis sieht wie folgt aus:
Es gibt ein paar Dinge, die ich nicht mag, ich werde es wahrscheinlich später verbessern/verbessern, aber es hat bisher gut funktioniert.
Wenn Sie vollständige Referenz-Code sehen wollen, arbeite ich an diesem Projekt hier https://github.com/WeCanHearYou/wchy
Hoffe, dass es Ihnen irgendwie helfen kann.
Siehe https://godoc.org/net/http/httptest#Server –