Golang:使用init()函数进行测试

huangapple go评论115阅读模式
英文:

Golang: Testing with init() func

问题

你好,我是你的中文翻译助手,以下是翻译好的内容:

你好,我刚开始学习Go语言,正在编写一个简单的应用程序,从环境变量中获取一些配置信息。我在init函数中进行了如下操作:

type envVars struct {
    Host     string `env:"APP_HOST"`
    Username string `env:"APP_USERNAME"`
    Password string `env:"APP_PASSWORD"`
}

var envConfig envVars

func init() {
    if err := env.Parse(&envConfig); err != nil {
        log.Fatal(err)
    }
}

我编写了测试来验证环境变量是否被正确读取。但问题是,我的程序的init函数在测试的init函数之前被调用。有没有办法在程序的init函数被调用之前进行一些设置呢?

func init() {
    os.Setenv("APP_HOST", "http://localhost:9999")
    os.Setenv("APP_USERNAME", "john")
    os.Setenv("APP_PASSWORD", "doe")
}

func TestEnvConfig(t *testing.T) {
    assert.NotNil(t, envConfig)
    assert.Equal(t, "http://localhost:9999", envConfig.Host)
}

希望对你有帮助!

英文:

Hi I am new to Go and I am writing a simple app which gets some configuration from the env variables. I do this in the init function as shown below.

type envVars struct {
	Host     string `env:"APP_HOST"`
	Username string `env:"APP_USERNAME"`
	Password string `env:"APP_PASSWORD"`
}

var envConfig envVars

func init() {
	if err := env.Parse(&envConfig); err != nil {
		log.Fatal(err)
	}
}

I wrote test to verify of the env variables are being read correctly. But the problem is that my program's init func gets called even before my test's init func. Is there any way I can do some sort of setup before my program's init func gets called.

func init() {
	os.Setenv("APP_HOST", "http://localhost:9999")
	os.Setenv("APP_USERNAME", "john")
	os.Setenv("APP_PASSWORD", "doe")
}

func TestEnvConfig(t *testing.T) {
	assert.NotNil(t, envConfig)
	assert.Equal(t, "http://localhost:9999", envConfig.Host)
}

答案1

得分: 11

你可以使用TestMain函数来控制测试之前和之后发生的事情。

例如:

func TestMain(m *testing.M) {
    // 在测试之前运行的代码
    
    // 运行测试
    exitVal := m.Run()
    
    // 在测试之后运行的代码

    // 使用测试的退出值退出
    os.Exit(exitVal)
}

func TestYourFunc(t *testing.T) {
    // 测试代码
}
英文:

You can use the TestMain func to control what happens before and after your tests.

For example:

func TestMain(m *testing.M) {
    // Write code here to run before tests
    
    // Run tests
    exitVal := m.Run()
    
    // Write code here to run after tests

    // Exit with exit value from tests
    os.Exit(exitVal)
}

func TestYourFunc(t *testing.T) {
    // Test code
}

答案2

得分: 0

你可以在真正的测试之前添加一个名为Test_parse_params(t *testing.T)的函数。代码如下所示:

type envVars struct {
    Host     string `env:"APP_HOST"`
    Username string `env:"APP_USERNAME"`
    Password string `env:"APP_PASSWORD"`
}

var envConfig envVars

// 解析命令参数
func Test_parse_params(t *testing.T) {
    if err := env.Parse(&envConfig); err != nil {
        log.Fatal(err)
    }
}

func Test_real_test(t *testing.T) {
    // 真正的测试代码
    ....
}

这段代码定义了一个名为envVars的结构体,其中包含了Host、Username和Password三个字段,它们分别对应着环境变量APP_HOST、APP_USERNAME和APP_PASSWORD。在Test_parse_params函数中,使用env.Parse函数来解析环境变量并将其赋值给envConfig变量。然后,在Test_real_test函数中,你可以编写真正的测试代码。

英文:

You can add a Test_parse_params(t *testing.T) function before your real tests. Look like this:

type envVars struct {
    Host     string `env:"APP_HOST"`
    Username string `env:"APP_USERNAME"`
    Password string `env:"APP_PASSWORD"`
}

var envConfig envVars

//parse command params
func Test_parse_params(t *testing.T) {
    if err := env.Parse(&envConfig); err != nil {
        log.Fatal(err)
    }
}

func Test_real_test(t *testing.T) {
....
}

答案3

得分: 0

不,你不应该期望init()按某种顺序运行(实际上它是基于文件加载顺序的,但你仍然不应该依赖它)。

简单的方法是,如果你想测试它,可以使用一个shell脚本来运行你的测试,或者类似Makefile的东西。

Shell示例:

set +e
export APP_HOST=http://localhost:9999
export APP_USERNAME=john
export APP_PASSWORD=doe
go test .
unset APP_HOST
unset APP_USERNAME
unset APP_PASSWORD

或者一行命令:

APP_HOST=http://localhost:9999 APP_USERNAME=john APP_PASSWORD=doe go test .

编辑:

另一种解决方案是将读取环境变量的代码移出init函数。

func init(){
  envInit()
}
func envInit(){
 if err := env.Parse(&envConfig); err != nil {
        log.Fatal(err)
    }
}

然后你可以在测试中再次调用envInit来确保它正常工作。

英文:

No, you shouldn't expect init() run in some order, (in fact it based on file loaded order, but still, you should not count on it).

The simple way is, if you want to test it, use a shell script to run you test, or something like Makefile.

Shell example:

set +e
export APP_HOST=http://localhost:9999
export APP_USERNAME=john
export APP_PASSWORD=doe
go test .
unset APP_HOST
unset APP_USERNAME
unset APP_PASSWORD

or a single line command:

APP_HOST=http://localhost:9999 APP_USERNAME=john APP_PASSWORD=doe go test .

Edit:

Other solution: move out the read env from init func.

func init(){
  envInit()
}
func envInit(){
 if err := env.Parse(&envConfig); err != nil {
        log.Fatal(err)
    }
}

Then you can call again envInit in your test to make sure it works.

答案4

得分: -1

不太理想,但这对我来说可行。在你正在测试的包内:

func init() {
    if len(os.Args) > 1 && os.Args[1][:5] == "-test" {
        log.Println("testing") // 这里可以进行特殊的测试设置
        return // ...或者完全跳过设置
    }
    //...
}
英文:

Less than ideal, but this works for me.
Inside of the package that you're testing:

func init() {
    if len(os.Args) > 1 && os.Args[1][:5] == "-test" {
    	log.Println("testing")//special test setup goes goes here
        return // ...or just skip the setup entirely
    }
    //...
}

huangapple
  • 本文由 发表于 2016年7月20日 23:39:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/38484942.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定