使用 init() 进行 Google 云函数 Golang 单元测试

标签 go google-cloud-platform google-cloud-functions

我在 Golang 中创建 Cloud Function 并为其创建单元测试时遇到问题。具体来说,我想在测试阶段注入(inject)的环境变量无法识别,因为 init() 函数总是在测试之前运行。此 init() 函数使用环境变量来创建客户端。有什么办法可以解决这个问题吗?

Google 建议将全局变量(如 clients)放入 init() 函数中,以便在以后的调用中重用这些对象。这减少了启动时间 ( source )。

目录结构

/function
  do_something.go
  do_something_test.go

do_something.go

package main

import (
    "context"
    "log"
    "os"

    "cloud.google.com/go/firestore"
)

var (
    projectID = os.Getenv("GCLOUD_PROJECT")
    client    *firestore.Client
)

func init() {
    ctx := context.Background()
    var err error
    client, err = firestore.NewClient(ctx, projectID)
    if err != nil {
        log.Fatalf("Firestore: %v", err)
    }
}

func Main(w http.ResponseWriter, r *http.Request) {
    // Do something
}

do_something_test.go

package main

import (
    "os"
    "testing"
)

func init() {
    os.Setenv("GCLOUD_PROJECT", "my-test-project") // This does not work because of lexigraphical order, init() in do_something.go before this init().
}

func TestMain(t *testing.T) {
    os.Setenv("GCLOUD_PROJECT", "my-test-project") // This does not work because init() is run before TestMain.
}

可能的解决方案

  1. 不要在 do_something.go 中使用 init()。但是,这会降低云功能的性能,由于启动时间延长,延迟会增加。
  2. 通过配置文件注入(inject)变量。但是,我认为这会带来同样的问题。
  3. 在运行 go test 之前设置环境变量。这是可行的,但我发现这是一个次优的解决方案,因为我不想在进行实际测试之前运行额外的参数。
  4. 除非环境变量指定代码在生产环境中运行,否则始终默认为开发环境:
projectID = GetEnv("GCLOUD_PROJECT", "my-test-project")

func GetEnv(key string, defaultVal string) string {
    if value, exists := os.LookupEnv(key); exists {
        return value
    }
    return defaultVal
}

最佳答案

您应该在项目级别公开一个环境变量,说明代码是在 test 设置还是在 prod 设置中执行。基于此,您的 init 函数将设置变量的值。

关于使用 init() 进行 Google 云函数 Golang 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68424906/

相关文章:

dns - 如何使用 gcloud dns 子命令?

google-app-engine - 我无法使用 google.golang.org/appengine 模块将 Go 模块部署到 App Engine

node.js - 更新 CloudFunctions 上的子集合

firebase - 如何每天自动备份Firestore数据库

google-app-engine - 为 go gae 共享一个本地主机?

Go - 如何使用 Pongo2 将模板渲染到临时字节缓冲区?

go - 在Golang中使用带有struct关键字的标签

go - 在 gomail v2 中发送带有可选附件的电子邮件

node.js - Elasticsearch Node.js 客户端 - 路由错误

node.js - Firebase 函数不使用 express.js 和 EJS View 引擎提供静态文件