gpt4 book ai didi

unit-testing - 如何在向 API 发送 http 请求时进行模拟

转载 作者:数据小太阳 更新时间:2023-10-29 03:25:55 25 4
gpt4 key购买 nike

我已经使用 go-gin 在 Go 中实现了一个 ReST API,我正在尝试测试一个如下所示的处理函数

func editNameHandler(c *gin.Context) {
// make a ReST call to another server
callToAnotherServer()
c.Status(200)
}

我想模拟 callToAnotherServer 方法,以便我的测试用例根本不调用第 3 方服务器。

我的测试用例看起来像

 func TestSeriveIdStatusRestorePatch(t *testing.T) {

// Request body
send := strings.NewReader(`{"name":"Robert"}`

// this function sends an HTTP request to the API which ultimately calls editNameHandler
// Ignore the variables.The variables are retrieved in code this is to simplify question
ValidTokenTestPatch(API_VERSION+"/accounts/"+TestAccountUUID+"/students/"+TestStudentId, t, send, http.StatusOK)
}

我经历了Mock functions in Go其中提到了我们如何将函数传递给 mock。我想知道我们如何在发送 http 请求时传递函数?在这种情况下我该如何模拟功能。最佳做法是什么?

最佳答案

我认为这个问题没有单一的答案,但我会分享我目前如何使用 go-gin 在 Go 上进行依赖注入(inject)的方法(但应该与任何其他路由器几乎相同).

从业务的角度来看,我有一个结构来包装对负责业务规则/处理的服务的所有访问。

// WchyContext is an application-wide context
type WchyContext struct {
Health services.HealthCheckService
Tenant services.TenantService
... whatever
}

我的服务只是接口(interface)。

// HealthCheckService is a simple general purpose health check service
type HealthCheckService interface {
IsDatabaseOnline() bool
}

它有多个实现,如 MockedHealthCheckPostgresHealthCheckPostgresTenantService 等。

我的路由器依赖于 WchyContext,代码如下所示:

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
}`

StatusTenantByDomain 就像一个处理程序工厂,它所做的就是根据给定的上下文创建一个新的处理程序,如下所示:

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"),
})
}
}

如您所见,我的健康检查处理程序不关心我的服务的具体实现,我只是使用 ctx.

中的任何内容

最后一部分取决于当前的执行环境。在自动化测试期间,我使用模拟/ stub 服务创建一个新的 WchyContext 并将其发送到 GetMainEngine,如下所示:

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

当您将其设置为真正监听 HTTP 端口时,接线如下所示:

var ctx context.WchyContext
var db *sql.DB

func init() {
db, _ = sql.Open("postgres", os.Getenv("DATABASE_URL"))

ctx = context.WchyContext{
Health: &services.PostgresHealthCheckService{DB: db},
Tenant: &services.PostgresTenantService{DB: db}
}
}

func main() {
handlers.GetMainEngine(ctx).Run(":" + util.GetEnvOrDefault("PORT", "3000"))
}

有一些我不喜欢的地方,我可能会在以后重构/改进它,但到目前为止它运行良好。

如果您想查看完整的代码引用,我正在这里处理这个项目 https://github.com/WeCanHearYou/wchy

希望能对你有所帮助。

关于unit-testing - 如何在向 API 发送 http 请求时进行模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41930482/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com