英文:
Init function breaking unit tests
问题
在我要测试的包中,我有一个初始化函数,它加载包含我想要用来运行应用程序的一些内容的配置文件。然而,在运行单元测试时,我不想触发这个初始化函数。
有没有办法在单元测试期间跳过或阻止调用这个初始化函数?
以下是一些代码片段来说明这个问题:
func init() {
var err error // 防止 config 变量被遮蔽
config, err = loadConfig("./client/config.yml")
if err != nil {
log.Fatal(err)
}
}
func loadConfig(filepath string) (*Config, error) {
viper.SetConfigFile(filepath)
if err := viper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("加载配置文件时出错:%s", err)
}
(...)
}
// New 返回一个 Config 值
func New() Config {
return *config
}
一个测试用例:
func TestNew(t *testing.T) {
expected := &Config{}
observed := New()
if !reflect.DeepEqual(observed, expected) {
t.Errorf("观察到的值为 %+v,期望的值为 %+v\n", observed, expected)
}
}
英文:
In the package I want to test, I have an init function that loads the configuration file containing some stuff I want to use to run my application. However, I don't want to trigger this init function while running my unit tests.
Is there any way for skipping or preventing this init function to be called during the unit tests?
Some snippets to illustrate the question:
func init() {
var err error // Necessary to prevent config variable shadowing
config, err = loadConfig("./client/config.yml")
if err != nil {
log.Fatal(err)
}
}
func loadConfig(filepath string) (*Config, error) {
viper.SetConfigFile(filepath)
if err := viper.ReadInConfig(); err != nil {
return nil, fmt.Errorf("Error loading config file: %s", err)
}
(...)
}
// New returns a Config value(!)
func New() Config {
return *config
}
A test case:
func TestNew(t *testing.T) {
expected := &Config{}
observed := New()
if !reflect.DeepEqual(observed, expected) {
t.Errorf("observed %+v. expecting %+v\n", observed, expected)
}
}
答案1
得分: 15
我不确定是否有更好的方法来做这个,但是如果你考虑到在运行init
函数之前,包级别的变量会被初始化,你可以使用一个标志来判断你是否正在运行测试。
var _testing = false
func init() {
if _testing {
return
}
var err error // 防止变量config被遮蔽
config, err = loadConfig("./client/config.yml")
if err != nil {
log.Fatal(err)
}
}
// ...
在你的测试文件中,你可以这样做:
```go
// 不太好看,但是有效
var _ = (func() interface{} {
_testing = true
return nil
}())
func TestNew(t *testing.T) {
expected := &Config{}
observed := New()
if !reflect.DeepEqual(observed, expected) {
t.Errorf("observed %+v. expecting %+v\n", observed, expected)
}
}
你可以在这里阅读更多关于初始化顺序的信息:https://golang.org/ref/spec#Program_initialization_and_execution
英文:
I'm not sure whether there's a nicer way of doing this, but if you consider the fact that package-level variables are initialized before the init
func is run you can use a flag to tell you whether you're running tests or not.
var _testing = false
func init() {
if _testing {
return
}
var err error // Necessary to prevent config variable shadowing
config, err = loadConfig("./client/config.yml")
if err != nil {
log.Fatal(err)
}
}
// ...
And in your test file you could do something like this:
// not nice but works
var _ = (func() interface{} {
_testing = true
return nil
}())
func TestNew(t *testing.T) {
expected := &Config{}
observed := New()
if !reflect.DeepEqual(observed, expected) {
t.Errorf("observed %+v. expecting %+v\n", observed, expected)
}
}
You can read more on the initialization order here: https://golang.org/ref/spec#Program_initialization_and_execution
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论