gocqlmock

package module
v0.0.0-...-63f5e64 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2019 License: MIT Imports: 6 Imported by: 0

README

Mock gocql

gocqlmock was designed to be useful with gocql library to mock common commands to cassandra database

Before

To mock gocql easily Your project should use gocql library through the interface. For example how to use base functionality: Query, Scan, Iter, Exec.


import (
	"github.com/gocql/gocql"
)

// SessionInterface should describe commonly used functions of the
// gocql.Session
type SessionInterface interface {
	Close()
	Query(string, ...interface{}) QueryInterface
    // Put more You need
}

// QueryInterface should describe commonly used functions of the
// gocql.Query
type QueryInterface interface {
	Exec() error
	Iter() IterInterface
	Scan(...interface{}) error
    // Put more You need
}

// IterInterface should describe commonly used functions of the
// gocql.Iter
type IterInterface interface {
	Close() error
	Scan(...interface{}) bool
    // Put more You need
}

// Sessions is a wrapper for a docql.Session for mockability
type Session struct {
	session *gocql.Session
}

// Query is a wrapper for a gocql.Query for mockability.
type Query struct {
	query *gocql.Query
}

// Iter is a wrapper for an gocql.Iter for mockability.
type Iter struct {
	iter *gocql.Iter
}

// NewSession instantiates a new Session
func NewSession(session *gocql.Session) SessionInterface {
	return &Session{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}
}

// Close wraps the session's close method
func (s *Session) Close() {
	s.session.Close()
}

// 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...)
}

// Close is a wrapper for the iter's Close method
func (i *Iter) Close() error {
	return i.iter.Close()
}

// Scan is a wrapper for the iter's Scan method
func (i *Iter) Scan(dest ...interface{}) bool {
	return i.iter.Scan(dest...)
}

Initialize gocql.Session

func NewConnection(hosts []string, keyspace string) (SessionInterface, error) {
	cluster := gocql.NewCluster(hosts...)
	cluster.Consistency = gocql.One

	if keyspace != "" {
		cluster.Keyspace = keyspace
	}

	session, err := cluster.CreateSession()
	if err != nil {
		return nil, err
	}

	return NewSession(session), err
}

Install

go get github.com/Agent-Plus/gocqlmock

Use

Once session interface was used in the project let's replace gocql with mock in the test. Create fake structs which will implement gocqlmock Session, Query, Iter.

import (
	"github.com/Agent-Plus/gocqlmock"
	"testing"
)

type MockSession struct {
	*gocqlmock.Session
}

type MockQuery struct {
	*gocqlmock.Query
}

type MockIter struct {
	*gocqlmock.Iter
}

func (s MockSession) Query(query string, args ...interface{}) dbapi.QueryInterface {
	return &MockQuery{s.Session.Query(query, args...)}
}

func (q MockQuery) Iter() dbapi.IterInterface {
	return &MockIter{q.Query.Iter()}
}

func (q MockQuery) Exec() error {
	return q.Query.Exec()
}

Test some handler

func TestGetUsers(t *testing.T) {
	testSession := &MockSession{gocqlmock.New(t)}
	testSession.ExpectQuery("SELECT.+FROM users").
		ExpectIter().
		WithResult(
			gocqlmock.NewRows().
				AddRow(int64(1)),
		)

	router := Server(testSession)
	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/users", nil)
	router.ServeHTTP(w, req)

	if w.Code != 200 {
        t.Error("expecgted response code 200")
    }
}
Expectations
Description
ExpectQuery Expected Query(...) call, will check query or arguments passed to the function Query(...)
ExpectScan Expected Query(...).Scan(...) call, this expectation will deliver fake row to the arguments passed through Scan(...)
ExpectIter Expected Query(...).Iter().Scan(...) call, this expectation will deliver fake rows to the arguments passed through Scan(...)
ExpectExec Expected Query(...).Exec() call
Row data

To create fake rows use WithResult, which follows with ExpectScan and ExpectQuery

	testSession.ExpectQuery("SELECT").
		ExpectIter().
		WithResult(
			gocqlmock.NewRows().
				AddRow(int64(1), "Foo", nil, 0, "8100000000", "foo@localhost").
				AddRow(int64(5), "Foo5", &AntStruct{Text: "F", BgColor: "#fff"}, 1, "8100000000", "foo5@localhost"),
		)
	testSession.ExpectQuery("SELECT.+WHERE.+id").
		ExpectScan().
		WithResult(
			gocqlmock.NewRows().
				AddRow(1),
		)

Thanks

Thanks to DATA-DOG for the go-sqlmock taken as idea for this

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Argument

type Argument interface {
	Match(interface{}) error
}

Argument interface allows to match any argument in specific way

type Iter

type Iter struct {
	// contains filtered or unexported fields
}

Iter represents an expectation with defined rows data to iterate

func (Iter) Close

func (i Iter) Close() error

Close returns error for the expectation or scan

func (*Iter) NumRows

func (i *Iter) NumRows() int

NumRows returns number of the rows

func (*Iter) Scan

func (i *Iter) Scan(dest ...interface{}) bool

Scan iterates through the rows

type Query

type Query struct {
	// contains filtered or unexported fields
}

Query represents query mock

func (*Query) Bind

func (q *Query) Bind(args ...interface{}) *Query

Bind

func (Query) Exec

func (m Query) Exec() error

Exec

func (Query) Iter

func (m Query) Iter() *Iter

Iter

func (Query) Scan

func (m Query) Scan(dest ...interface{}) error

Scan

type Rows

type Rows interface {
	AddRow(...interface{}) Rows
}

Rows interface manages the collection of the data rows

func NewRows

func NewRows() Rows

NewRows returns new mock storage for the rows data

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session represents the mock of the expectations of the query, iterators and scan actions

func New

func New(t *testing.T) *Session

New creates empty Session mock to be filled with expection scanarios

func TestSomeCassandraQuery(t *testing.T) {
    testSession := gocqlmock.New(t)

    // expecting single query
    testSession.ExpectQuery("SELECT .+ FROM users").
        ExpectScan().
        WithResult(
            gocqlmock.NewRows().
                AddRow(234)
        )

    router := Server(testSession)
    w := httptest.NewRecorder()
    req, _ := http.NewRequest("GET", "/user/234", nil)
    router.ServeHTTP(w, req)
}
func TestSomeCassandraQueryWithListResult(t *testing.T) {
    testSession := gocqlmock.New(t)

    // expecting single query
    testSession.ExpectQuery("SELECT .+ FROM groups").
        ExpectIter().
        WithResult(
            gocqlmock.NewRows().
                AddRow(2, "Group 2", 1.2).
                AddRow(5, "Group 5", 4.6)
        )

    router := Server(testSession)
    w := httptest.NewRecorder()
    req, _ := http.NewRequest("GET", "/groups", nil)
    router.ServeHTTP(w, req)
}

func (Session) Close

func (m Session) Close()

Close is an empty wrap

func (*Session) ExpectExec

func (m *Session) ExpectExec() *Session

ExpectExec Query(...).Exec() to be triggered

func (*Session) ExpectIter

func (m *Session) ExpectIter() *Session

ExpectIter Query(...).Iter().Scan(...) to be triggered, which will assign values from the rows mock to the arguments passed through Scan(...)

func (*Session) ExpectQuery

func (m *Session) ExpectQuery(queryRegex string) *Session

ExpectQuery Query(...) to be triggered, which will match the given query string as a regular expression

func (*Session) ExpectScan

func (m *Session) ExpectScan() *Session

ExpectScan Query(...).Scan(...) to be triggered, which will assign values from the rows mock to the arguments passed through Scan(...)

func (Session) Query

func (m Session) Query(query string, args ...interface{}) (q *Query)

Query

func (*Session) WithArgs

func (m *Session) WithArgs(args ...interface{}) *Session

WithArgs expectation should be called with given arguments. Works with Query expectations and Exec expectation

testSession.ExpectQuery("SELECT .+ FROM tb WHERE id").

WithArgs(1).
ExpectExec()

testSession.ExpectQuery("UPDATE").

ExpectExec().
WithArgs(1)

func (*Session) WithError

func (m *Session) WithError(args ...interface{}) *Session

WithError expectation will return error

func (*Session) WithResult

func (m *Session) WithResult(r Rows) *Session

WithResult assignes rows mock to the expectation wich was created through ExpectScan or ExpectIter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL