diff --git a/Makefile b/Makefile index 68dc49dc0..2a22e2caa 100644 --- a/Makefile +++ b/Makefile @@ -279,6 +279,11 @@ msg: @echo "${NOW} Starting to build rpc_msg..." CGO_ENABLED=0 GOOS=${OS} GOARCH=${ARCH};go build -ldflags="-w -s" -o ./bin/openim-rpc-msg cmd/openim-rpc/openim-rpc-msg/main.go +.PHONY:test-user +test-user: + @echo "${NOW} Starting to test rpc_user..." + go test ./internal/rpc/user + .PHONY:user user: @echo "${NOW} Starting to build rpc_user..." diff --git a/go.mod b/go.mod index 939988d15..d73f43df3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/openimsdk/open-im-server/v3 -go 1.19 +go 1.21 require ( firebase.google.com/go v3.13.0+incompatible @@ -118,6 +118,7 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/xid v1.5.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/scram v1.1.2 // indirect diff --git a/go.sum b/go.sum index 37d568861..05f72e9a5 100644 --- a/go.sum +++ b/go.sum @@ -318,6 +318,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= diff --git a/go.work b/go.work index 6800fa496..0415fc713 100644 --- a/go.work +++ b/go.work @@ -1,16 +1,18 @@ -go 1.18 +go 1.21 + +toolchain go1.23.2 use ( . ./test/typecheck ./tools/changelog + ./tools/component + ./tools/data-conversion //./tools/imctl ./tools/infra ./tools/ncpu ./tools/openim-web + ./tools/url2im ./tools/versionchecker ./tools/yamlfmt - ./tools/component - ./tools/url2im - ./tools/data-conversion ) diff --git a/internal/rpc/user/mocks/DataProvider.go b/internal/rpc/user/mocks/DataProvider.go new file mode 100644 index 000000000..c4cf12bc1 --- /dev/null +++ b/internal/rpc/user/mocks/DataProvider.go @@ -0,0 +1,52 @@ +// Code generated by mockery v2.46.2. DO NOT EDIT. + +package mocks + +import mock "github.com/stretchr/testify/mock" + +// DataProvider is an autogenerated mock type for the DataProvider type +type DataProvider struct { + mock.Mock +} + +// GetRandomNumber provides a mock function with given fields: id +func (_m *DataProvider) GetRandomNumber(id int) (int, error) { + ret := _m.Called(id) + + if len(ret) == 0 { + panic("no return value specified for GetRandomNumber") + } + + var r0 int + var r1 error + if rf, ok := ret.Get(0).(func(int) (int, error)); ok { + return rf(id) + } + if rf, ok := ret.Get(0).(func(int) int); ok { + r0 = rf(id) + } else { + r0 = ret.Get(0).(int) + } + + if rf, ok := ret.Get(1).(func(int) error); ok { + r1 = rf(id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewDataProvider creates a new instance of DataProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewDataProvider(t interface { + mock.TestingT + Cleanup(func()) +}) *DataProvider { + mock := &DataProvider{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/rpc/user/mocks/UserDatabase.go b/internal/rpc/user/mocks/UserDatabase.go new file mode 100644 index 000000000..9098a0bd0 --- /dev/null +++ b/internal/rpc/user/mocks/UserDatabase.go @@ -0,0 +1,463 @@ +// Code generated by mockery v2.46.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" + + relation "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + + time "time" + + user "github.com/OpenIMSDK/protocol/user" +) + +// UserDatabase is an autogenerated mock type for the UserDatabase type +type UserDatabase struct { + mock.Mock +} + +// CountRangeEverydayTotal provides a mock function with given fields: ctx, start, end +func (_m *UserDatabase) CountRangeEverydayTotal(ctx context.Context, start time.Time, end time.Time) (map[string]int64, error) { + ret := _m.Called(ctx, start, end) + + if len(ret) == 0 { + panic("no return value specified for CountRangeEverydayTotal") + } + + var r0 map[string]int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) (map[string]int64, error)); ok { + return rf(ctx, start, end) + } + if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) map[string]int64); ok { + r0 = rf(ctx, start, end) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]int64) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, time.Time, time.Time) error); ok { + r1 = rf(ctx, start, end) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CountTotal provides a mock function with given fields: ctx, before +func (_m *UserDatabase) CountTotal(ctx context.Context, before *time.Time) (int64, error) { + ret := _m.Called(ctx, before) + + if len(ret) == 0 { + panic("no return value specified for CountTotal") + } + + var r0 int64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *time.Time) (int64, error)); ok { + return rf(ctx, before) + } + if rf, ok := ret.Get(0).(func(context.Context, *time.Time) int64); ok { + r0 = rf(ctx, before) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context, *time.Time) error); ok { + r1 = rf(ctx, before) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Create provides a mock function with given fields: ctx, users +func (_m *UserDatabase) Create(ctx context.Context, users []*relation.UserModel) error { + ret := _m.Called(ctx, users) + + if len(ret) == 0 { + panic("no return value specified for Create") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []*relation.UserModel) error); ok { + r0 = rf(ctx, users) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Find provides a mock function with given fields: ctx, userIDs +func (_m *UserDatabase) Find(ctx context.Context, userIDs []string) ([]*relation.UserModel, error) { + ret := _m.Called(ctx, userIDs) + + if len(ret) == 0 { + panic("no return value specified for Find") + } + + var r0 []*relation.UserModel + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]*relation.UserModel, error)); ok { + return rf(ctx, userIDs) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []*relation.UserModel); ok { + r0 = rf(ctx, userIDs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*relation.UserModel) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, userIDs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FindWithError provides a mock function with given fields: ctx, userIDs +func (_m *UserDatabase) FindWithError(ctx context.Context, userIDs []string) ([]*relation.UserModel, error) { + ret := _m.Called(ctx, userIDs) + + if len(ret) == 0 { + panic("no return value specified for FindWithError") + } + + var r0 []*relation.UserModel + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]*relation.UserModel, error)); ok { + return rf(ctx, userIDs) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []*relation.UserModel); ok { + r0 = rf(ctx, userIDs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*relation.UserModel) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, userIDs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAllSubscribeList provides a mock function with given fields: ctx, userID +func (_m *UserDatabase) GetAllSubscribeList(ctx context.Context, userID string) ([]string, error) { + ret := _m.Called(ctx, userID) + + if len(ret) == 0 { + panic("no return value specified for GetAllSubscribeList") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) ([]string, error)); ok { + return rf(ctx, userID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok { + r0 = rf(ctx, userID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, userID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetAllUserID provides a mock function with given fields: ctx, pageNumber, showNumber +func (_m *UserDatabase) GetAllUserID(ctx context.Context, pageNumber int32, showNumber int32) ([]string, error) { + ret := _m.Called(ctx, pageNumber, showNumber) + + if len(ret) == 0 { + panic("no return value specified for GetAllUserID") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, int32, int32) ([]string, error)); ok { + return rf(ctx, pageNumber, showNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, int32, int32) []string); ok { + r0 = rf(ctx, pageNumber, showNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int32, int32) error); ok { + r1 = rf(ctx, pageNumber, showNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetSubscribedList provides a mock function with given fields: ctx, userID +func (_m *UserDatabase) GetSubscribedList(ctx context.Context, userID string) ([]string, error) { + ret := _m.Called(ctx, userID) + + if len(ret) == 0 { + panic("no return value specified for GetSubscribedList") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) ([]string, error)); ok { + return rf(ctx, userID) + } + if rf, ok := ret.Get(0).(func(context.Context, string) []string); ok { + r0 = rf(ctx, userID) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, userID) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetUserStatus provides a mock function with given fields: ctx, userIDs +func (_m *UserDatabase) GetUserStatus(ctx context.Context, userIDs []string) ([]*user.OnlineStatus, error) { + ret := _m.Called(ctx, userIDs) + + if len(ret) == 0 { + panic("no return value specified for GetUserStatus") + } + + var r0 []*user.OnlineStatus + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) ([]*user.OnlineStatus, error)); ok { + return rf(ctx, userIDs) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) []*user.OnlineStatus); ok { + r0 = rf(ctx, userIDs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*user.OnlineStatus) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, userIDs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// InitOnce provides a mock function with given fields: ctx, users +func (_m *UserDatabase) InitOnce(ctx context.Context, users []*relation.UserModel) error { + ret := _m.Called(ctx, users) + + if len(ret) == 0 { + panic("no return value specified for InitOnce") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []*relation.UserModel) error); ok { + r0 = rf(ctx, users) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// IsExist provides a mock function with given fields: ctx, userIDs +func (_m *UserDatabase) IsExist(ctx context.Context, userIDs []string) (bool, error) { + ret := _m.Called(ctx, userIDs) + + if len(ret) == 0 { + panic("no return value specified for IsExist") + } + + var r0 bool + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, []string) (bool, error)); ok { + return rf(ctx, userIDs) + } + if rf, ok := ret.Get(0).(func(context.Context, []string) bool); ok { + r0 = rf(ctx, userIDs) + } else { + r0 = ret.Get(0).(bool) + } + + if rf, ok := ret.Get(1).(func(context.Context, []string) error); ok { + r1 = rf(ctx, userIDs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Page provides a mock function with given fields: ctx, pageNumber, showNumber +func (_m *UserDatabase) Page(ctx context.Context, pageNumber int32, showNumber int32) ([]*relation.UserModel, int64, error) { + ret := _m.Called(ctx, pageNumber, showNumber) + + if len(ret) == 0 { + panic("no return value specified for Page") + } + + var r0 []*relation.UserModel + var r1 int64 + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, int32, int32) ([]*relation.UserModel, int64, error)); ok { + return rf(ctx, pageNumber, showNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, int32, int32) []*relation.UserModel); ok { + r0 = rf(ctx, pageNumber, showNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*relation.UserModel) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, int32, int32) int64); ok { + r1 = rf(ctx, pageNumber, showNumber) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(context.Context, int32, int32) error); ok { + r2 = rf(ctx, pageNumber, showNumber) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// SetUserStatus provides a mock function with given fields: ctx, list +func (_m *UserDatabase) SetUserStatus(ctx context.Context, list []*user.OnlineStatus) error { + ret := _m.Called(ctx, list) + + if len(ret) == 0 { + panic("no return value specified for SetUserStatus") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []*user.OnlineStatus) error); ok { + r0 = rf(ctx, list) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SubscribeUsersStatus provides a mock function with given fields: ctx, userID, userIDs +func (_m *UserDatabase) SubscribeUsersStatus(ctx context.Context, userID string, userIDs []string) error { + ret := _m.Called(ctx, userID, userIDs) + + if len(ret) == 0 { + panic("no return value specified for SubscribeUsersStatus") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok { + r0 = rf(ctx, userID, userIDs) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UnsubscribeUsersStatus provides a mock function with given fields: ctx, userID, userIDs +func (_m *UserDatabase) UnsubscribeUsersStatus(ctx context.Context, userID string, userIDs []string) error { + ret := _m.Called(ctx, userID, userIDs) + + if len(ret) == 0 { + panic("no return value specified for UnsubscribeUsersStatus") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string) error); ok { + r0 = rf(ctx, userID, userIDs) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Update provides a mock function with given fields: ctx, _a1 +func (_m *UserDatabase) Update(ctx context.Context, _a1 *relation.UserModel) error { + ret := _m.Called(ctx, _a1) + + if len(ret) == 0 { + panic("no return value specified for Update") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *relation.UserModel) error); ok { + r0 = rf(ctx, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdateByMap provides a mock function with given fields: ctx, userID, args +func (_m *UserDatabase) UpdateByMap(ctx context.Context, userID string, args map[string]interface{}) error { + ret := _m.Called(ctx, userID, args) + + if len(ret) == 0 { + panic("no return value specified for UpdateByMap") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, map[string]interface{}) error); ok { + r0 = rf(ctx, userID, args) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// NewUserDatabase creates a new instance of UserDatabase. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewUserDatabase(t interface { + mock.TestingT + Cleanup(func()) +}) *UserDatabase { + mock := &UserDatabase{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/internal/rpc/user/service/data_provider.go b/internal/rpc/user/service/data_provider.go new file mode 100644 index 000000000..f4fe8922c --- /dev/null +++ b/internal/rpc/user/service/data_provider.go @@ -0,0 +1,5 @@ +package service + +type DataProvider interface { + GetRandomNumber(id int) (int, error) +} diff --git a/internal/rpc/user/service/data_provider_impl.go b/internal/rpc/user/service/data_provider_impl.go new file mode 100644 index 000000000..0f98638ff --- /dev/null +++ b/internal/rpc/user/service/data_provider_impl.go @@ -0,0 +1,18 @@ +package service + +import ( + "errors" + "math/rand" +) + +// DataProviderImpl is the concrete implementation of the DataProvider interface. +type DataProviderImpl struct{} + +// GetRandomNumber simulates fetching a random number between 0 and id. +func (d *DataProviderImpl) GetRandomNumber(id int) (int, error) { + if id < 0 { + return 0, errors.New("InvalidId") + } + // Simulate fetching a random number between 0 and id + return rand.Intn(id + 1), nil +} diff --git a/internal/rpc/user/user_test.go b/internal/rpc/user/user_test.go new file mode 100644 index 000000000..298b9aea6 --- /dev/null +++ b/internal/rpc/user/user_test.go @@ -0,0 +1,100 @@ +package user + +import ( + "context" + "fmt" + "testing" + + pbuser "github.com/OpenIMSDK/protocol/user" + "github.com/openimsdk/open-im-server/v3/internal/rpc/user/mocks" + "github.com/openimsdk/open-im-server/v3/internal/rpc/user/service" + "github.com/openimsdk/open-im-server/v3/pkg/common/db/table/relation" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +var mockUserDatabase = &mocks.UserDatabase{} + +// var uServer userServer + +// func inti() { + +// } + +func TestGetDesignateUsers(t *testing.T) { + + uServer := userServer{UserDatabase: mockUserDatabase} + + mockUserDatabase.On("FindWithError", mock.Anything, mock.Anything).Return([]*relation.UserModel{{UserID: "99"}}, nil) + ctx := context.Background() + + res, err := uServer.GetDesignateUsers(ctx, &pbuser.GetDesignateUsersReq{UserIDs: []string{}}) + + assert.NoError(t, err) + assert.Equal(t, "99", res.UsersInfo[0].UserID) + + t.Logf("success") +} + +type MyMockedObject struct { + mock.Mock +} + +func (m *MyMockedObject) DoSomeThing(number int) (bool, error) { + args := m.Called(number) + return args.Bool(0), args.Error(1) +} + +func TestDataProvider(t *testing.T) { + + testOjb := new(MyMockedObject) + testOjb.On("DoSomeThing", mock.Anything).Return(true, nil) + + targetFuncThatDoesSomethingWithObj(*testOjb) + + testOjb.AssertExpectations(t) + + /////// + + mock := &mocks.DataProvider{} + + // Set the expected return value for the GetRandomNumber method + mock.On("GetRandomNumber", 5).Return(3, nil).Once() + // Call ConsumeData that using the mocked DataProvider + result, err := ConsumeData(mock, 5) + // Assert that the result and error are as expected + assert.Equal(t, "Odd", result) + assert.NoError(t, err) + // Assert that the GetRandomNumber method was called with the expected input + mock.AssertExpectations(t) +} + +func targetFuncThatDoesSomethingWithObj(testObj MyMockedObject) { + fmt.Println(testObj.DoSomeThing(12)) +} + +// ConsumeData is a function that uses a DataProvider to fetch and process data. +func ConsumeData(provider service.DataProvider, id int) (string, error) { + // Use GetRandomNumber to get a random number between 0 and id + randomNumber, err := provider.GetRandomNumber(id) + if err != nil { + return "", err + } + // Check whether the value is even or odd + result := checkEvenOrOdd(randomNumber) + // Return the result + return result, nil +} + +// checkEvenOrOdd checks whether the given value is even or odd. +func checkEvenOrOdd(value int) string { + if value%2 == 0 { + return "Even" + } + return "Odd" +} + +//mockery --dir ../../../pkg/common/db/controller --name UserDatabase +//mockery --all --output path/to/output +//mockery --all --recursive +//mockery --output ./mocks --dir ./service --all diff --git a/jenkins-deploy/jenkinsfiles/api.jenkinsfile b/jenkins-deploy/jenkinsfiles/api.jenkinsfile index 5b229bd2a..14a3045cf 100644 --- a/jenkins-deploy/jenkinsfiles/api.jenkinsfile +++ b/jenkins-deploy/jenkinsfiles/api.jenkinsfile @@ -58,6 +58,14 @@ pipeline { ]) } } + + stage("Unit-Test") { + steps { + echo 'UNIT TEST EXECUTION STARTED' + sh 'make test-user' + } + } + stage('CommitHash') { steps { script { @@ -113,8 +121,7 @@ pipeline { extensions: [], gitTool: 'Default', submoduleCfg: [], - userRemoteConfigs: [[url: "https://github.com/${ORGANIZATION_NAME}/${SERVICE_NAME_INFRA}", credentialsId: "${CREDENTIALS_ID}"]] - ]) + userRemoteConfigs: [[url: "https://github.com/${ORGANIZATION_NAME}/${SERVICE_NAME_INFRA}", credentialsId: "${CREDENTIALS_ID}"]]]) } } diff --git a/test/rpc/user/user_test.go b/test/rpc/user/user_test.go new file mode 100644 index 000000000..e3e3cb80c --- /dev/null +++ b/test/rpc/user/user_test.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/mock" +) + +type MyMockedObject struct { + mock.Mock +} + +func (m *MyMockedObject) DoSomeThing(number int) (bool, error) { + args := m.Called(number) + return args.Bool(0), args.Error(1) +} + +// var uServer = userServer{} + +func TestGetDesignateUsers(t *testing.T) { + testOjb := new(MyMockedObject) + testOjb.On("DoSomeThing", mock.Anything).Return(true, nil) + + targetFuncThatDoesSomethingWithObj(*testOjb) + + testOjb.AssertExpectations(t) + + t.Logf("success") +} + +func targetFuncThatDoesSomethingWithObj(testObj MyMockedObject) { + fmt.Println(testObj.DoSomeThing(12)) +}