我试图在我的测试文件中模拟 Go 函数 os.GetEnv(),以便我可以获得特定环境变量的所需值。
比如我已经定义了。abc := os.GetEnv("XYZ_URL")在这里,我应该能够获得变量 abc 所需的值。我还有几个地方有 GetEnv 函数。
如果有人可以在没有任何 Go 框架帮助的情况下给我一个解决方法,那将非常有帮助。

最佳答案

首先,您不能模拟该功能。您只能模拟作为接口(interface)公开的内容。
其次,你可能不需要。从广义上讲,模拟被过度使用,应尽可能避免。
测试环境变量时,您有四个常规选项:

  • 创建一个可以模拟/加倍的对象,它公开了必要的功能。示例:

  • type OS interface {
        Getenv(string) string
    }
    
    type defaultOS struct{}
    
    func (defaultOS) Getenv(key string) string {
        return os.Getenv(key)
    }
    
    // Then in your code, replace `os.Getenv()` with:
    
    myos := defaultOS{}
    value := myos.Getenv("XYZ_URL")
    
    在您的测试中,创建一个满足接口(interface)的自定义实现,但提供您测试所需的值。
    这种方法对某些事情很有用(比如包装 time 包),但对于 os.Getenv 来说可能是一种不好的方法。
  • 使你的函数不依赖于 os.Getenv ,而只是传入值。 示例,而不是:

  • func connect() (*DB, error) {
        db, err := sql.Connect(os.Getenv("XYZ_URL"), ...)
        /* ... */
        return db, err
    }
    
    用:
    func connect(url string) (*DB, error) {
        db, err := sql.Connect(url, ...)
        /* ... */
        return db, err
    }
    
    从某种意义上说,这只是“移动”了问题——您可能仍然想测试使用 os.Getenv() 的调用者,但您至少可以减少依赖于这种方法的 API 的表面积,这使得第三种方法更容易.
  • 在测试期间明确设置环境。示例:

  • func TestFoo(t *testing.T) {
        orig := os.Getenv("XYZ_URL")
        os.Setenv("XYZ_URL", "http://example.com")
        t.Cleanup(func() { os.Setenv("XYZ_URL", orig) })
        /* do your tests here */
    }
    
    这种方法确实有局限性。特别是,并行运行多个这些测试是行不通的,因此您仍然希望尽量减少运行的这些测试的数量。
    这意味着方法 2 和方法 3 相互结合可以非常强大。
  • 最后一个选项是创建一个可以在测试中替换的函数变量。我已经讨论过这个 in another post ,但对于你的例子,它可能看起来像这样:

  • var getenv = os.Getenv
    
    /* ... then in your code ... */
    
    func foo() {
        value := getenv("XYZ_URL") // Instead of calling os.Getenv directly
    }
    
    并在测试中:
    func TestFoo(t *testing.T) {
        getenv = func(string) string { return "http://example.com/" }
        /* ... your actual tests ... */
    }
    
    这与选项 #3 有许多相同的限制,因为您不能并行运行多个测试,因为它们会发生冲突。

    关于unit-testing - 模拟 os.GetEnv ("ENV_VAR"),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/66061175/

    10-11 23:51