Last active
February 22, 2023 07:42
-
-
Save mrrizal/bac93535df6fb5c79ffdc9ddd5a49882 to your computer and use it in GitHub Desktop.
Implementing Interfaces for GoCQL lib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func NewMockService(logger commons.Logger, session custom_gocql.SessionInterface) Service { | |
return &Service{session: session, logger: logger} | |
} | |
// InitMockFunc it's use for implelementing the interface. | |
// it's just mock, so just put empty function | |
func InitMockFunc() { | |
session.ExecutedQuery = []string{} | |
session.MockQuery = func(stmt string, val ...interface{}) custom_gocql.QueryInterface { | |
session.ExecutedQuery = append(session.ExecutedQuery, NormalizeString(stmt)) | |
return &query | |
} | |
query.MockWithContext = func(ctx context.Context) custom_gocql.QueryInterface { | |
return &query | |
} | |
query.MockExec = func() error { | |
return nil | |
} | |
query.MockPageSize = func(i int) custom_gocql.QueryInterface { | |
return &query | |
} | |
query.MockWithContext = func(ctx context.Context) custom_gocql.QueryInterface { | |
return &query | |
} | |
query.MockIter = func() custom_gocql.IterInterface { | |
return &iter | |
} | |
iter.MockScanner = func() gocql.Scanner { | |
return scanner | |
} | |
scanner.MockNext = func() bool { | |
return true | |
} | |
scanner.MockScan = func(i ...interface{}) error { | |
return nil | |
} | |
} | |
// testSaveFeed function for test SaveFeed | |
func testSaveFeed(t *testing.T) { | |
expectedString := {"your expected query"} | |
expectedString = NormalizeString(expectedString) | |
RunTest(func() { | |
t.Run("SaveFeed.Ok", func(t *testing.T) { | |
// create mock service | |
svc := NewMockService(logger, &session) | |
// dont forget to call `InitMockFunc` to implement SaveFeed, | |
// if not it will raise error | |
err := svc.SaveFeed(ctx, &models.Feed{}) | |
assert.Equal(t, nil, err) | |
assert.Equal(t, expectedString, session.ExecutedQuery[0]) | |
}) | |
}) | |
RunTest(func() { | |
t.Run("SaveFeed.Error", func(t *testing.T) { | |
// at InitMockFunc, the MockExec func return success | |
// but for this test, we want the MockExec func return, | |
// so this the way how to achive that | |
query.MockExec = func() error { | |
return errors.New("error") | |
} | |
svc := NewMockService(logger, &session) | |
err := svc.SaveFeed(ctx, &models.Feed{}) | |
assert.NotEqual(t, nil, err) | |
}) | |
}) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
func NewService(logger commons.Logger, session *gocql.Session) Service { | |
// we use interface instead of directly gocql | |
s := custom_gocql.NewSession(session) | |
return &Service{session: s, logger: logger} | |
} | |
// SaveFeed function for saving feed to db | |
func (fs *service) SaveFeed(ctx context.Context, objFeed *models.Feed) error { | |
dataJSON, err := json.Marshal(objFeed.Data) | |
if err != nil { | |
return err | |
} | |
// at this statement, we not use "real" gocql, we use the interface | |
err = fs.session.Query({"your query"}).WithContext(ctx).Exec() | |
return err | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// interface for gocql | |
package custom_gocql | |
import ( | |
"context" | |
"github.com/gocql/gocql" | |
) | |
// SessionInterface allows gomock custom_gocql of gocql.Session | |
type SessionInterface interface { | |
Query(string, ...interface{}) QueryInterface | |
} | |
// QueryInterface allows gomock custom_gocql of gocql.Query | |
type QueryInterface interface { | |
Bind(...interface{}) QueryInterface | |
Exec() error | |
Iter() IterInterface | |
Scan(...interface{}) error | |
WithContext(context.Context) QueryInterface | |
PageSize(int) QueryInterface | |
} | |
// IterInterface allows gomock custom_gocql of gocql.Iter | |
type IterInterface interface { | |
Scan(...interface{}) bool | |
Scanner() gocql.Scanner | |
} | |
// Session is a wrapper for a session for mockability. | |
type Session struct { | |
session *gocql.Session | |
} | |
// Query is a wrapper for a query for mockability. | |
type Query struct { | |
query *gocql.Query | |
} | |
// Iter is a wrapper for an iter for mockability. | |
type Iter struct { | |
iter *gocql.Iter | |
} | |
// NewSession instantiates a new Session | |
func NewSession(session *gocql.Session) SessionInterface { | |
return &Session{ | |
session, | |
} | |
} | |
// NewQuery instantiates a new Query | |
func NewQuery(query *gocql.Query) QueryInterface { | |
return &Query{ | |
query, | |
} | |
} | |
// NewIter instantiates a new Iter | |
func NewIter(iter *gocql.Iter) IterInterface { | |
return &Iter{ | |
iter, | |
} | |
} | |
// Query wraps the session's query method | |
func (s *Session) Query(stmt string, values ...interface{}) QueryInterface { | |
return NewQuery(s.session.Query(stmt, values...)) | |
} | |
// Bind wraps the query's Bind method | |
func (q *Query) Bind(v ...interface{}) QueryInterface { | |
return NewQuery(q.query.Bind(v...)) | |
} | |
// Exec wraps the query's Exec method | |
func (q *Query) Exec() error { | |
return q.query.Exec() | |
} | |
// Iter wraps the query's Iter method | |
func (q *Query) Iter() IterInterface { | |
return NewIter(q.query.Iter()) | |
} | |
// Scan wraps the query's Scan method | |
func (q *Query) Scan(dest ...interface{}) error { | |
return q.query.Scan(dest...) | |
} | |
func (q *Query) WithContext(ctx context.Context) QueryInterface { | |
return NewQuery(q.query.WithContext(ctx)) | |
} | |
func (q *Query) PageSize(n int) QueryInterface { | |
return NewQuery(q.query.PageSize(n)) | |
} | |
// Scan is a wrapper for the iter's Scan method | |
func (i *Iter) Scan(dest ...interface{}) bool { | |
return i.iter.Scan(dest...) | |
} | |
func (i *Iter) Scanner() gocql.Scanner { | |
return i.iter.Scanner() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// mock use for mocking gocql interface | |
package custom_gocql | |
import ( | |
"context" | |
"github.com/gocql/gocql" | |
) | |
type MockSession struct { | |
ExecutedQuery []string | |
MockQuery func(string, ...interface{}) QueryInterface | |
} | |
type MockQuery struct { | |
MockBind func(...interface{}) QueryInterface | |
MockExec func() error | |
MockIter func() IterInterface | |
MockScan func(...interface{}) error | |
MockWithContext func(context.Context) QueryInterface | |
MockPageSize func(int) QueryInterface | |
} | |
type MockIter struct { | |
mockScan func(...interface{}) bool | |
MockScanner func() gocql.Scanner | |
} | |
type MockScanner struct { | |
MockNext func() bool | |
MockScan func(...interface{}) error | |
MockErr func() error | |
} | |
func (s MockScanner) Next() bool { | |
return s.MockNext() | |
} | |
func (s MockScanner) Scan(val ...interface{}) error { | |
return s.MockScan(val...) | |
} | |
func (s MockScanner) Err() error { | |
return s.MockErr() | |
} | |
func NewMockSession() MockSession { | |
return MockSession{} | |
} | |
func NewMockQuery() MockQuery { | |
return MockQuery{} | |
} | |
func NewMockIter() MockIter { | |
return MockIter{} | |
} | |
func NewMockScanner() MockScanner { | |
return MockScanner{} | |
} | |
func (s *MockSession) Query(stmt string, val ...interface{}) QueryInterface { | |
return s.MockQuery(stmt, val...) | |
} | |
// Bind wraps the query's Bind method | |
func (q *MockQuery) Bind(v ...interface{}) QueryInterface { | |
return q.MockBind(v...) | |
} | |
// Exec wraps the query's Exec method | |
func (q *MockQuery) Exec() error { | |
return q.MockExec() | |
} | |
// Iter wraps the query's Iter method | |
func (q *MockQuery) Iter() IterInterface { | |
return q.MockIter() | |
} | |
// Scan wraps the query's Scan method | |
func (q *MockQuery) Scan(dest ...interface{}) error { | |
return q.MockScan(dest...) | |
} | |
func (q *MockQuery) WithContext(ctx context.Context) QueryInterface { | |
return q.MockWithContext(ctx) | |
} | |
func (q *MockQuery) PageSize(n int) QueryInterface { | |
return q.MockPageSize(n) | |
} | |
func (i *MockIter) Scan(val ...interface{}) bool { | |
return i.mockScan(val...) | |
} | |
func (i *MockIter) Scanner() gocql.Scanner { | |
return i.MockScanner() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment