require.ErrorIsでエラーが一緒に見えるのに通らない時に見て欲しいこと[Go]

goでtestをしているときにtestifyパッケージのrequire.ErrorIsでメソッドを用いて、エラーの検証がしたいときに、下のようなエラーが発生したことがありました。

```
return fmt.Errorf("error: %s", gorm.ErrNotFound)
```

```go
require.ErrorIs(t, err, tt.wantErr)
```

エラーをよく見ると欲しいエラー文と実際のエラー文が同じなのに、テストが通りませんでした。
```zsh
--- FAIL: TestUpdate (0.00s)
    --- FAIL: TestUpdate (0.00s)
        code_test.go:173:
                Error:          Target error should be in err chain:
                                expected: "error:  not found"
                                in chain: "error:  not found"

FAIL
```

エラー文が同一なのに通らなかったテストを通した際にわかったことをメモとしてまとめておきたいなと思います。

# そもそもErrorIsメソッドとは
ErrorIsメソッドは、`errors`パッケージのIsメソッドで行っているエラーチェーン内に特定のエラーが含まれているかを調べるメソッドです。

:::note
### エラーチェーンとは
別パッケージ発生したエラーをラッピングして辿れるようにしたものです。

エラーを見た時に複数ファイルにおいて、このようなエラーが発生したとコンソール上に出てくると思います。

エラーを辿れるようにして、エラーがどのメソッドを通してどこが大元でエラーを吐いてるかを調べれるようにした仕組みをエラーチェーンと言います。
:::

例えば、goのORMライブラリとして有名なGORMで用意されている`NotFound`エラーがエラーチェーンに含まれてるかどうかという時に`errors.Is`メソッドを使用できます。
↓

https://qiita.com/maooz4426/items/fa1aa9a1a8c8c3a10701

`require.ErrorIs`では、`errors.Is`のようにテストケース内で発生したエラーのエラーチェーンにおいて特定のエラーが含まれているかどうかができる、抽象メソッドです。

# どうしてエラーが出てしまったのか
エラー文は同じだけど違うエラーが出ているということは、`ErrorIsメソッド`の話で気づけるようにエラーチェーンが違う可能性が考えられると思います。

ではどうしてエラーチェーンが異なってしまったかというと、Goにおける`フォーマット指定子`が関係しています。

フォーマット指定子は下のような`%`で指定して、表示形式を決めているものです。

```go
fmt.Sprintf("hello %s", w)
```

フォーマット指定子は`%`のあとに指定子で指定されている文字によって指定できるものが変わってきます。

一部例を出すと下のようになっています。

|指定子|型|
|---|---
|%v|value
|%t|bool
|%d|10進数(int)
|%s|文字列(string)
|%p|ポインタ

今回のコードでは`%s`でstringを指定していると思います。
```go
fmt.Errorf("error: %s", repository.ErrNotFound)
```

こうすることによって`error: not found`で一つのエラーになってしまいます。

今回はエラーチェーンとして`error: not found`から`gorm.ErrNotFound`のエラー文である`not found`が`ErrorIs`メソッドで取り出されて欲しいのに、エラーチェーンが形成されず取り出すことができなかったので、テストが通らなかったというわけです。

エラーチェーンが形成されるようにするには、下のように実装します。
```go
fmt.Errorf("mutual fund not found: %w", repository.ErrNotFound)
```

ドキュメントによると、`%w`を指定子に指定することでfmtで作成してくれるエラーに`Unwrap`メソッドを実装してくれます。

https://pkg.go.dev/fmt#Errorf

こうすることでエラーチェーンとして機能し、`ErrorIs`メソッドでエラーが含まれているかを調べるようにできるようになり、エラーが辿りやすくなります。

`fmt.Errorf`でエラー文を整形したいとなった時、テストでエラーが通らなくなった時はぜひ参考にしてください。

# Go関連の記事
https://qiita.com/maooz4426/items/fa1aa9a1a8c8c3a10701

https://qiita.com/maooz4426/items/4e70baae712c9e19300e

https://qiita.com/maooz4426/items/b01f0502a2c1cdc914c9

https://qiita.com/maooz4426/items/49aef802e3a178ed5bd6

https://qiita.com/maooz4426/items/b973490dd005e3d8e9de

https://qiita.com/maooz4426/items/f6740347eec6df320a1e

https://qiita.com/maooz4426/items/44a71129ce2f0a463817

https://qiita.com/maooz4426/items/1ab385f3aceeb660e500

https://qiita.com/maooz4426/items/422a8d6428c2504efe23

https://qiita.com/maooz4426/items/592028f297ca76830c6b

https://qiita.com/maooz4426/items/63071aba6a69c9a55ef4

https://qiita.com/maooz4426/items/e1af6b5994e0c6c067d7

https://qiita.com/maooz4426/items/575b36ded6eadfda36b0

https://qiita.com/maooz4426/items/e1933175e492883db26d

https://qiita.com/maooz4426/items/a61bbc6c32a349ce71ee

https://qiita.com/maooz4426/items/91fa49341bc2e9d8eddd

https://qiita.com/maooz4426/items/2f9fe5e8d6b6a44b3d57

https://qiita.com/maooz4426/items/17cbad84213a222df694

https://qiita.com/maooz4426/items/698b0f8ee4c43b465d8c

https://qiita.com/maooz4426/items/c26a5e7abecc676c56d9