2

I have a error type like below defined

type RetryableError struct {
    msg string
}

func (a *RetryableError) Error() string {
    return a.msg
}

In a unit test, what is the Go way of asserting if the error returned is of RetryableError type?

Anirudh Jayakumar
  • 1,171
  • 3
  • 15
  • 37
  • 2
    This, along with many other Go basics, is covered in the Tour of Go: https://tour.golang.org/methods/15 – Adrian Aug 29 '19 at 21:58

2 Answers2

6

Use type assertion:

err := someFunc()
if retryable, ok := err.(*RetryableError); ok {
   // use retryable
}

Your RetryableError is not an error, but *RetryableError is. To correct:

func (a RetryableError) Error() string {
    return a.msg
}
Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • Unfortunately this does not work: [Go Playground](https://play.golang.org/p/QZN2tgGW8RC). The error has a wonderful description on [SO here](https://stackoverflow.com/questions/40823315/x-does-not-implement-y-method-has-a-pointer-receiver), but I still haven't found the right way to typecheck for errors. – phdesign Dec 17 '20 at 05:39
  • Yes it does. Your `Retryable` is not an error, but `*Retryable` is: https://play.golang.org/p/qwpPFSB0R_b – Burak Serdar Dec 17 '20 at 05:41
  • @BurakSerdar Maybe you could edit your answer accordingly to avoid confusion? – Ben Hoyt Jan 28 '21 at 00:51
  • IMO, tests are supposed to be deterministic and any condition in tests are to be avoided since they increase cyclomatic complexity. If such conditions are really needed, they themselves should be tested. `assert`/`require` are prefered, though. – Noel Yap Mar 28 '23 at 14:11
5

assert.IsType

Snippet from https://medium.com/@sebdah/go-best-practices-testing-3448165a0e18:

func TestDivision(t *testing.T) {
    tests := []struct{
        x      float64
        y      float64
        result float64
        err    error
    }{
        { x: 1.0, y: 2.0, result: 0.5, err: nil },
        { x: -1.0, y: 2.0, result: -0.5, err: nil},
        { x: 1.0, y: 0.0, result: 0.0, err: ErrZeroDivision},
    }
    for _, test := range tests {
        result, err := divide(test.x, test.y)
        assert.IsType(t, test.err, err)
        assert.Equal(t, test.result, result)
    }
}
Noel Yap
  • 18,822
  • 21
  • 92
  • 144