Skip to content

Commit

Permalink
Update /programming/gomock-custom-matcher (#5038)
Browse files Browse the repository at this point in the history
* Update /programming/gomock-custom-matcher

Use fork (go.uber.org/mock) instead

* Update type definitions
  • Loading branch information
chitoku-k authored Dec 3, 2023
1 parent 9650195 commit 13db77a
Showing 1 changed file with 21 additions and 21 deletions.
42 changes: 21 additions & 21 deletions contents/posts/programming/gomock-custom-matcher.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
---
title: GoMock の Matcher を自作して gomock.Any() 回避!
title: gomock の Matcher を自作して gomock.Any() 回避!
created: 2020-05-24T22:25:50+09:00
category: プログラミング
tags:
- Go
---
Go でテストを記述する際、モックの生成にはしばしば [GoMock](https://pkg.go.dev/github.com/golang/mock/gomock) が使われますが、引数の検証に使う [Matcher](https://pkg.go.dev/github.com/golang/mock/gomock#Matcher) は標準では限られたもののみが用意されています。
Go でテストを記述する際、モックの生成にはしばしば [gomock](https://pkg.go.dev/go.uber.org/mock) が使われますが、引数の検証に使う [Matcher](https://pkg.go.dev/go.uber.org/mock/gomock#Matcher) は標準では限られたもののみが用意されています。

たとえば、以下のテストの 12 行目では `go¦gomock.Eq(...)` を使って `go¦api.Client` に対して `go¦Get("/v1/info")` という呼び出しが 1 回されることを期待しています。

Expand All @@ -29,7 +29,7 @@ type Client interface {
import (
"testing"
"github.com/golang/mock/gomock"
"go.uber.org/mock/gomock"
)
func TestServiceGet(t *testing.T) {
Expand All @@ -53,7 +53,7 @@ func TestServiceGet(t *testing.T) {
import (
"testing"
"github.com/golang/mock/gomock"
"go.uber.org/mock/gomock"
)
func TestServicePost(t *testing.T) {
Expand Down Expand Up @@ -105,15 +105,15 @@ func (s *service) DoFancyStuff() {

## 環境

+--------+--------+
| Go | 1.16.6 |
+--------+--------+
| GoMock | 1.6.0 |
+--------+--------+
+------------------+--------+
| Go | 1.21.4 |
+------------------+--------+
| go.uber.org/mock | 0.3.0 |
+------------------+--------+

## 設計

GoMock には別の Matcher を入れ子に持つ `go¦Not`[^2] のような Matcher がすでにあるため、汎化するために `go¦io.Reader` を検証する Reader の Matcher と、`go¦url.Values` を検証する Query の Matcher の 2 つに分けて、以下のように呼び出せるようにしておきます。
gomock には別の Matcher を入れ子に持つ `go¦Not`[^2] のような Matcher がすでにあるため、汎化するために `go¦io.Reader` を検証する Reader の Matcher と、`go¦url.Values` を検証する Query の Matcher の 2 つに分けて、以下のように呼び出せるようにしておきます。

```go
mock.EXPECT().Post(
Expand Down Expand Up @@ -162,14 +162,14 @@ func Query(m gomock.Matcher) gomock.Matcher {

```go
type Matcher interface {
Matches(x interface{}) bool
Matches(x any) bool
String() string
}
```

```go
type GotFormatter interface {
Got(got interface{}) string
Got(got any) string
}
```

Expand All @@ -183,7 +183,7 @@ import (
"fmt"
"io"
"github.com/golang/mock/gomock"
"go.uber.org/mock/gomock"
)
type readerMatcher struct {
Expand All @@ -196,7 +196,7 @@ func Reader(m gomock.Matcher) gomock.Matcher {
return gomock.GotFormatterAdapter(r, r)
}
func (r *readerMatcher) Matches(x interface{}) bool {
func (r *readerMatcher) Matches(x any) bool {
var err error
r.data, err = io.ReadAll(x.(io.Reader))
if err != nil {
Expand All @@ -209,7 +209,7 @@ func (r *readerMatcher) String() string {
return fmt.Sprintf("data(%s)", r.m.String())
}
func (r *readerMatcher) Got(got interface{}) string {
func (r *readerMatcher) Got(got any) string {
f, ok := r.m.(gomock.GotFormatter)
if ok {
// highlight-next-line
Expand All @@ -229,7 +229,7 @@ import (
"fmt"
"net/url"
"github.com/golang/mock/gomock"
"go.uber.org/mock/gomock"
)
type queryMatcher struct {
Expand All @@ -247,7 +247,7 @@ func Query(m gomock.Matcher) gomock.Matcher {
)
}
func (q *queryMatcher) Matches(x interface{}) bool {
func (q *queryMatcher) Matches(x any) bool {
values, err := url.ParseQuery(string(x.([]byte)))
if err != nil {
return false
Expand All @@ -259,7 +259,7 @@ func (q *queryMatcher) String() string {
return fmt.Sprintf("url.Values(%s)", q.m.String())
}
func (q *queryGotFormatter) Got(got interface{}) string {
func (q *queryGotFormatter) Got(got any) string {
values, _ := url.ParseQuery(string(got.([]byte)))
f, ok := q.m.(gomock.GotFormatter)
if ok {
Expand Down Expand Up @@ -297,6 +297,6 @@ FAIL
## 脚注

[^1]: 本来は単に実装側で [Client.PostForm(string, url.Values)](https://pkg.go.dev/net/http#Client.PostForm) を使えば済みます
[^2]: [func Not(interface{}) Matcher](https://pkg.go.dev/github.com/golang/mock/gomock#Not)
[^3]: [GotFormatter](https://pkg.go.dev/github.com/golang/mock/gomock#GotFormatter)
[^4]: [func GotFormatterAdapter(GotFormatter, Matcher) Matcher](https://pkg.go.dev/github.com/golang/mock/gomock#GotFormatterAdapter)
[^2]: [func Not(any) Matcher](https://pkg.go.dev/go.uber.org/mock/gomock#Not)
[^3]: [GotFormatter](https://pkg.go.dev/go.uber.org/mock/gomock#GotFormatter)
[^4]: [func GotFormatterAdapter(GotFormatter, Matcher) Matcher](https://pkg.go.dev/go.uber.org/mock/gomock#GotFormatterAdapter)

0 comments on commit 13db77a

Please sign in to comment.