diff --git a/_example/mock_example/mock.go b/_example/mock_example/mock.go new file mode 100644 index 0000000..7a3ec2f --- /dev/null +++ b/_example/mock_example/mock.go @@ -0,0 +1,49 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: repo.go + +// Package mock_example is a generated GoMock package. +package mock_example + +import ( + context "context" + _example "github.com/budougumi0617/cmpmock/_example" + gomock "github.com/golang/mock/gomock" + reflect "reflect" +) + +// MockUserRepo is a mock of UserRepo interface +type MockUserRepo struct { + ctrl *gomock.Controller + recorder *MockUserRepoMockRecorder +} + +// MockUserRepoMockRecorder is the mock recorder for MockUserRepo +type MockUserRepoMockRecorder struct { + mock *MockUserRepo +} + +// NewMockUserRepo creates a new mock instance +func NewMockUserRepo(ctrl *gomock.Controller) *MockUserRepo { + mock := &MockUserRepo{ctrl: ctrl} + mock.recorder = &MockUserRepoMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockUserRepo) EXPECT() *MockUserRepoMockRecorder { + return m.recorder +} + +// Save mocks base method +func (m *MockUserRepo) Save(arg0 context.Context, arg1 *_example.User) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Save", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// Save indicates an expected call of Save +func (mr *MockUserRepoMockRecorder) Save(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Save", reflect.TypeOf((*MockUserRepo)(nil).Save), arg0, arg1) +} diff --git a/_example/repo.go b/_example/repo.go new file mode 100644 index 0000000..396b137 --- /dev/null +++ b/_example/repo.go @@ -0,0 +1,28 @@ +package _example + +import ( + "context" + "time" +) + +type User struct { + Name, Address string + CreateAt time.Time +} + +type UserRepo interface { + Save(context.Context, *User) error +} + +type UserUsecase struct { + Repo UserRepo +} + +func (uu *UserUsecase) Register(ctx context.Context, name, address string) error { + u := &User{ + Name: name, + Address: address, + CreateAt: time.Now(), + } + return uu.Repo.Save(ctx, u) +} diff --git a/_example/repo_test.go b/_example/repo_test.go new file mode 100644 index 0000000..5af6b3c --- /dev/null +++ b/_example/repo_test.go @@ -0,0 +1,34 @@ +package _example_test + +import ( + "context" + "testing" + "time" + + "github.com/budougumi0617/cmpmock" + "github.com/budougumi0617/cmpmock/_example" + "github.com/budougumi0617/cmpmock/_example/mock_example" + "github.com/golang/mock/gomock" +) + +func TestUserUsecase_Save(t *testing.T) { + ctrl := gomock.NewController(t) + t.Cleanup(ctrl.Finish) + ctx := context.Background() + name := "John Due" + address := "Tokyo" + wantUser := &_example.User{ + Name: name, + Address: address, + CreateAt: time.Now(), + } + + mrepo := mock_example.NewMockUserRepo(ctrl) + mrepo.EXPECT().Save(ctx, cmpmock.DiffEq(wantUser)).Return(nil) + + sut := _example.UserUsecase{Repo: mrepo} + + if err := sut.Register(ctx, name, address); err != nil { + t.Fatal(err) + } +} diff --git a/diffmatcher.go b/diffmatcher.go new file mode 100644 index 0000000..234501f --- /dev/null +++ b/diffmatcher.go @@ -0,0 +1,35 @@ +package cmpmock + +import ( + "fmt" + "time" + + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" +) + +func DiffEq(v interface{}, opts ...cmp.Option) gomock.Matcher { + var lopts cmp.Options + if len(opts) == 0 { + lopts = append(lopts, cmpopts.EquateApproxTime(1*time.Second)) + } else { + lopts = append(lopts, opts...) + } + return &diffMatcher{want: v, opts: lopts} +} + +type diffMatcher struct { + want interface{} + diff string + opts cmp.Options +} + +func (d *diffMatcher) Matches(x interface{}) bool { + d.diff = cmp.Diff(x, d.want, d.opts...) + return len(d.diff) == 0 +} + +func (d *diffMatcher) String() string { + return fmt.Sprintf("diff(-got +want) is %s", d.diff) +} diff --git a/diffmatcher_test.go b/diffmatcher_test.go new file mode 100644 index 0000000..4795f41 --- /dev/null +++ b/diffmatcher_test.go @@ -0,0 +1,50 @@ +package cmpmock + +import ( + "fmt" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func Test_DiffEq(t *testing.T) { + type Foo struct{ CreateAt time.Time } + t1 := time.Now() + t2 := t1.Add(100 * time.Millisecond) + defaultString := "diff(-got +want) is %s" + type args struct { + want interface{} + opts cmp.Options + } + tests := []struct { + name string + args args + x Foo + wantMatch bool + wantDiff string + }{ + { + name: "diff less than a second with default option", + args: args{ + want: Foo{CreateAt: t1}, + opts: nil, + }, + x: Foo{CreateAt: t2}, + wantMatch: true, + wantDiff: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sut := DiffEq(tt.args.want, tt.args.opts...) + x := Foo{CreateAt: t2} + if got := sut.Matches(x); got != tt.wantMatch { + t.Errorf("Matches() = %v, want %v", got, tt.wantMatch) + } + if got := sut.String(); got != fmt.Sprintf(defaultString, tt.wantDiff) { + t.Errorf("String() = %q, want %q", got, tt.wantDiff) + } + }) + } +} diff --git a/go.mod b/go.mod index 8793f50..e97d4f6 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,8 @@ module github.com/budougumi0617/cmpmock go 1.16 + +require ( + github.com/golang/mock v1.5.0 + github.com/google/go-cmp v0.5.5 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b555648 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=