首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在向API发送http请求时进行模拟

如何在向API发送http请求时进行模拟
EN

Stack Overflow用户
提问于 2017-01-30 15:01:17
回答 1查看 1.1K关注 0票数 0

我已经使用go-gin在Go中实现了一个ReST应用程序接口,并且我正在尝试测试一个如下所示的处理程序函数

代码语言:javascript
复制
func editNameHandler(c *gin.Context) {
        // make a ReST call to another server
        callToAnotherServer()
        c.Status(200)
}

我想模拟callToAnotherServer方法,这样我的测试用例就根本不会调用第三方服务器。

我的测试用例看起来像这样

代码语言:javascript
复制
 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请求时传递函数?在这种情况下,我如何模拟函数。最佳实践是什么?

EN

回答 1

Stack Overflow用户

发布于 2017-01-31 21:06:29

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

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

代码语言:javascript
复制
// WchyContext is an application-wide context
type WchyContext struct {
    Health   services.HealthCheckService
    Tenant   services.TenantService
    ... whatever
}

那么我的服务就只是接口了。

代码语言:javascript
复制
// HealthCheckService is a simple general purpose health check service
type HealthCheckService interface {
    IsDatabaseOnline() bool
}

它们有多个实现,比如MockedHealthCheckPostgresHealthCheckPostgresTenantService等等。

我的路由器依赖于一个WchyContext,它的代码如下:

代码语言:javascript
复制
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就像一个处理程序工厂,它所做的就是根据给定的上下文创建一个新的处理程序,如下所示:

代码语言:javascript
复制
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.中的任何内容

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

代码语言:javascript
复制
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端口时,布线如下所示:

代码语言:javascript
复制
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上做这个项目

希望它能以某种方式帮助你。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41930482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档