postgresr

package module
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: May 11, 2023 License: MIT Imports: 7 Imported by: 1

README

Postgresr

Postgresr (pronounced post-gres-er) is a thin wrapper round the library pgx. It provides interfaces and mocks that can be used for establishing real connections, as well as mocking your database interactions for unit testing. As of this writing this does not implement all methods on pgx.Conn, but it implements enough for my purposes.

Install

go get github.com/app-nerds/postgrer

Example

package main

import (
  "context"

  "github.com/app-nerds/postgresr"
)

func main() {
  var (
    err error
	 db postgresr.Conn
  )

  if db, err = postgresr.Connect(context.Background(), "host=localhost dbname=example user=user password=password"); err != nil {
    panic("cannot connect to database!")
  }


}

Testing

This library provides mock structures useful for unit tests. Here is an example of a test that mocks a Postgres variable passed to a function.

func QueryForStuff(pg postgresr.Conn) ([]SomeStruct, error) {
	var (
		err error
		rows pgx.Rows
		result []SomeStruct
	)

	query := `SELECT * FROM that_table WHERE something='else'`

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
	defer cancel()

	if rows, err = pg.Query(ctx, query); err != nil {
		// handle it
	}

	for rows.Next() {
		var (
			column1 string
			column2 int
		)

		if err = rows.Scan(&column1, &column2); err != nil {
			// handle it
		}

		result = append(result, SomeStruct{
			Column1: column1,
			Column2: column2,
		})
	}

	return result, nil
}

func TestQueryForStuff(t *testing.T) {
	testData := [][]interface{}{
		{
			"value1", // column1
			1,         // column2
		},
		{
			"value2",
			2,
		},
	}

	pg := &postgresr.MockConn{
		QueryFunc: postgresr.MockQuerySuccessHelper(testData),
	}

	want := []SomeStruct{
		{ Column1: "value1", Column2: 1 },
		{ Column1: "value2", Column2: 2 },
	}

	got, err := QueryForStuff(pg)

	if err != nil {
		t.Errorf("didn't expect an error!")
	}

	if !reflect.DeepEqual(want, got) {
		t.Errorf("wanted: %+v\ngot: %+v\n", want, got)
	}
}

If you need more control of what you return in query mocks, the DataToRows method might be useful.

func TestQueryForStuff(t *testing.T) {
	var (
		data1CurrentRow *int
		data1TotalCount *int
		data2CurrentRow *int
		data2TotalCount *int
	)

	testData1 := [][]interface{}{
		{
			"value1", // column1
			1,         // column2
		},
		{
			"value2",
			2,
		},
	}

	testData2 := [][]interface{}{
		{ 1, "1" },
		{ 2, "2" },
	}

	data1Counter := postgresr.InitializeRowCounterFunc(data1CurrentRow, data1TotalCount, len(testData1))
	data2Counter := postgresr.InitializeRowCounterFunc(data2CurrentRow, data2TotalCount, len(testData2))

	pg := &postgresr.MockConn{
		QueryFunc: func(ctx context.Context, query string, arguments ...interface{}) (pgx.Rows, error) {
			if strings.Contains(query, "FROM table1") {
				return postgresr.DataToRows(testData1, data1Counter), nil
			}

			return postgresr.DataToRows(testData2, data2Counter), nil
		},
	}

	want := []SomeStruct{
		{ Column1: "value1", Column2: 1 },
		{ Column1: "value2", Column2: 2 },
	}

	got, err := QueryForStuff(pg)

	if err != nil {
		t.Errorf("didn't expect an error!")
	}

	if !reflect.DeepEqual(want, got) {
		t.Errorf("wanted: %+v\ngot: %+v\n", want, got)
	}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DataToRows added in v1.2.0

func DataToRows(rows [][]interface{}, rowCounterFunc RowCounterFunc) pgx.Rows

func MockQuerySuccessHelper added in v1.1.0

func MockQuerySuccessHelper(rows [][]interface{}) func(ctx context.Context, query string, args ...interface{}) (pgx.Rows, error)

Types

type Conn

type Conn interface {
	Close(ctx context.Context) error
	Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)
	Ping(ctx context.Context) error
	Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row
}

func Connect

func Connect(ctx context.Context, connString string) (Conn, error)

func ConnectConfig

func ConnectConfig(ctx context.Context, connConfig *pgx.ConnConfig) (Conn, error)

type MockConn

type MockConn struct {
	CloseFunc    func(ctx context.Context) error
	ExecFunc     func(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)
	PingFunc     func(ctx context.Context) error
	QueryFunc    func(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
	QueryRowFunc func(ctx context.Context, sql string, args ...interface{}) pgx.Row
}

func (*MockConn) Close

func (m *MockConn) Close(ctx context.Context) error

func (*MockConn) Exec

func (m *MockConn) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)

func (*MockConn) Ping

func (m *MockConn) Ping(ctx context.Context) error

func (*MockConn) Query

func (m *MockConn) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)

func (*MockConn) QueryRow

func (m *MockConn) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row

type MockRow

type MockRow struct {
	ScanFunc func(dest ...interface{}) error
}

func (*MockRow) Scan

func (m *MockRow) Scan(dest ...interface{}) error

type MockRows

type MockRows struct {
	CloseFunc             func()
	CommandTagFunc        func() pgconn.CommandTag
	ErrFunc               func() error
	FieldDescriptionsFunc func() []pgproto3.FieldDescription
	GetTotalRowsFunc      func() uint64
	NextFunc              func() bool
	ScanFunc              func(dest ...interface{}) error
	ValuesFunc            func() ([]interface{}, error)
	RawValuesFunc         func() [][]byte
}

func (*MockRows) Close

func (m *MockRows) Close()

func (*MockRows) CommandTag

func (m *MockRows) CommandTag() pgconn.CommandTag

func (*MockRows) Err

func (m *MockRows) Err() error

func (*MockRows) FieldDescriptions

func (m *MockRows) FieldDescriptions() []pgproto3.FieldDescription

func (*MockRows) GetTotalRows added in v1.1.0

func (m *MockRows) GetTotalRows() uint64

func (*MockRows) Next

func (m *MockRows) Next() bool

func (*MockRows) RawValues

func (m *MockRows) RawValues() [][]byte

func (*MockRows) Scan

func (m *MockRows) Scan(dest ...interface{}) error

func (*MockRows) Values

func (m *MockRows) Values() ([]interface{}, error)

type PgxConn

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

func (*PgxConn) Close

func (c *PgxConn) Close(ctx context.Context) error

func (*PgxConn) Exec

func (c *PgxConn) Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)

func (*PgxConn) Ping

func (c *PgxConn) Ping(ctx context.Context) error

func (*PgxConn) Query

func (c *PgxConn) Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)

func (*PgxConn) QueryRow

func (c *PgxConn) QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row

type RowCounterFunc added in v1.2.1

type RowCounterFunc func() (*int, *int)

func InitializeRowCounterFunc added in v1.2.1

func InitializeRowCounterFunc(currentRowTracker *int, totalRowsTracker *int, totalRows int) RowCounterFunc

type Scanner

type Scanner interface {
	Scan(dst ...interface{}) error
}

Jump to

Keyboard shortcuts

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