2017-04-14 61 views
1

在我想測試的包中,我有一個init函數,用於加載配置文件,其中包含一些我想用來運行我的應用程序的東西。但是,我不想在運行單元測試時觸發這個init函數。初始化函數中斷單元測試

有沒有什麼辦法可以在單元測試中跳過或防止這個init函數被調用?

一些片段來說明這個問題:

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 
} 

測試用例:

func TestNew(t *testing.T) { 
    expected := &Config{} 
    observed := New() 
    if !reflect.DeepEqual(observed, expected) { 
     t.Errorf("observed %+v. expecting %+v\n", observed, expected) 
    } 
} 
+3

我會強烈建議不要在加載配置init()函數,出於所述的原因(測試問題)等(結構,可重用性,控制等)。只需從入口點調用loadConfig()即可。 – Adrian

回答

3

我不知道是否有這樣做的更好的方式,但如果你考慮的是,在運行init func之前初始化包級變量,您可以使用標誌來告訴您是否運行測試。

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

// ... 

並在測試文件中,你可以做這樣的事情:

// 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) 
    } 
} 

你可以閱讀更多的初始化命令在這裏:https://golang.org/ref/spec#Program_initialization_and_execution

+1

感謝您的回答。我決定不使用'init()'。在'New'函數中調用'loadConfig'並返回該函數中的錯誤似乎更加適用。 –

相關問題