【问题标题】:How to unit test Go errors如何对 Go 错误进行单元测试
【发布时间】:2017-06-21 11:10:38
【问题描述】:

当您对具有error 返回类型的函数进行单元测试时,我想知道如何正确地对该错误进行单元测试。您是否应该只检查错误是否为零?或者您是否应该验证错误字符串也与预期字符串匹配?

【问题讨论】:

  • 我不认为这是重复的@030,因为另一个问题只是比较错误。这个问题是关于如何有效地比较单元测试中的错误。这些不是完全相同的问题,我对它们的回答会有所不同。

标签: unit-testing go error-handling


【解决方案1】:

是的,我测试了返回错误的函数并检查错误消息是否匹配。但是你是要检查还是只检查错误不是nil,这取决于你。

假设你有这样的功能:

func returnSomeErr(input int)error{
    if input > 0{
        return nil
    }
    return errors.New("this is error message")
}

您可以像这样对错误消息进行单元测试:

// testing tot get error message
func TestReturnSomeErr(t *testing.T){
   Expected := "this is error message"
   actual := returnSomeErr(-1)

   if actual.Error() != Expected{
        t.Errorf("Error actual = %v, and Expected = %v.", actual, test.Expected)
   }
}

请注意,我正在使用.Error() 函数来获取错误消息,以便将其与字符串进行比较。如果输入数据> 0,则可以创建另一个测试来测试是否没有错误。

【讨论】:

    【解决方案2】:

    在大多数情况下,您只需检查错误是否不为零。

    除非绝对必要,否则我建议不要检查错误字符串。我通常认为错误字符串仅供人类使用。

    如果您需要有关错误的更多详细信息,一种更好的选择是自定义错误类型。然后您可以切换 err.(type) 并查看它是否是您期望的类型。 如果您需要更多详细信息,可以使自定义错误类型包含值,然后您可以在测试中检查这些值。

    Go 的错误只是具有Error() string 方法的类型的接口,因此您自己实现它们很简单。 https://blog.golang.org/error-handling-and-go

    【讨论】:

    • 我确实喜欢使用自定义错误类型的想法,这肯定会简化事情。
    【解决方案3】:

    我经常使用这个简单的函数来检查错误:

    // ErrorContains checks if the error message in out contains the text in
    // want.
    //
    // This is safe when out is nil. Use an empty string for want if you want to
    // test that err is nil.
    func ErrorContains(out error, want string) bool {
        if out == nil {
            return want == ""
        }
        if want == "" {
            return false
        }
        return strings.Contains(out.Error(), want)
    }
    

    示例用法:

    if !ErrorContains(err, "unexpected banana") {
        t.Errorf("unexpected error: %v", err)
    }
    
    if !ErrorContains(err, "") {
        t.Errorf("unexpected error: %v", err)
    }
    

    我发现这在表驱动测试中特别有用,因为我可以执行以下操作:

    tests := struct{
        want    string
        wantErr string
    }{
        {
            "some output",
            "",  // No error expected
        },
        {
            "",
            "out of coconuts",
        }
    }
    

    它避免了与nilerrors.New() 之类的混淆。

    我使用string.Contains() 而不是检查完整错误,因为这样更可靠。我只想知道这是否是我所期望的大致错误(而不是完全不相关的错误)。我很少检查完整的错误消息,而是使用关键字(例如“意外结束”、“不够”等)


    这个函数是github.com/teamwork/test 包的一部分(我是那个包的主要作者),但如果我只使用这个函数而不使用那个包中的其他函数,我经常只是复制/粘贴它。

    【讨论】:

      【解决方案4】:

      证明package会派上用场。

      来自文档:“EqualErrorf 断言函数返回错误(即不是nil)并且它等于提供的错误。”:

      assert.EqualErrorf(t, err, expectedErrorMsg, "Error should be: %v, got: %v", expectedErrorMsg, err)
      

      断言错误消息包含子字符串:

      assert.Containsf(t, err.Error(), tt.wantErrMsg, "expected error containing %q, got %s", tt.wantErrMsg, err)
      

      t 的类型为 *testing.Terr 的类型为 error

      【讨论】:

        猜你喜欢
        • 2015-08-26
        • 2019-10-12
        • 2012-01-08
        • 2019-11-02
        • 1970-01-01
        • 1970-01-01
        • 2020-06-22
        • 2021-07-01
        相关资源
        最近更新 更多