ksql/mocks_test.go

480 lines
14 KiB
Go

// This test was written mostly for test coverage since the mock is trivial
package ksql_test
import (
"context"
"fmt"
"testing"
"github.com/vingarcia/ksql"
tt "github.com/vingarcia/ksql/internal/testtools"
)
func TestMock(t *testing.T) {
UsersTable := ksql.NewTable("users", "id")
type User struct {
ID int `ksql:"id"`
Name string `ksql:"name"`
Age int `ksql:"age"`
}
t.Run("testing unset behaviors for all methods", func(t *testing.T) {
t.Run("Insert should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
mock.Insert(ctx, UsersTable, &User{
Name: "fake-name",
Age: 42,
})
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.Insert(", "ksql.Mock.InsertFn", "not set")
})
t.Run("Patch should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
mock.Patch(ctx, UsersTable, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.Patch(", "ksql.Mock.PatchFn", "not set")
})
t.Run("Delete should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
mock.Delete(ctx, UsersTable, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.Delete(", "ksql.Mock.DeleteFn", "not set")
})
t.Run("Query should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
var users []User
mock.Query(ctx, &users, "SELECT * FROM user WHERE age = ?", 42)
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.Query(", "ksql.Mock.QueryFn", "not set")
})
t.Run("QueryOne should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
var user User
mock.QueryOne(ctx, &user, "SELECT * FROM user WHERE id = ?", 4242)
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.QueryOne(", "ksql.Mock.QueryOneFn", "not set")
})
t.Run("QueryChunks should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
var users []User
mock.QueryChunks(ctx, ksql.ChunkParser{
Query: "SELECT * FROM users WHERE age = ?",
Params: []interface{}{
4242,
},
ChunkSize: 10,
ForEachChunk: func(chunk []User) error {
users = append(users, chunk...)
return nil
},
})
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.QueryChunks(", "ksql.Mock.QueryChunksFn", "not set")
})
t.Run("Exec should panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
panicPayload := tt.PanicHandler(func() {
mock.Exec(ctx, "INSERT INTO users_permissions(user_id, permission_id) VALUES (?, ?)", 4242, 4)
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.Mock.Exec(", "ksql.Mock.ExecFn", "not set")
})
t.Run("Transaction should not panic", func(t *testing.T) {
ctx := context.Background()
mock := ksql.Mock{}
executed := false
panicPayload := tt.PanicHandler(func() {
mock.Transaction(ctx, func(db ksql.Provider) error {
executed = true
return nil
})
})
tt.AssertEqual(t, panicPayload, nil)
tt.AssertEqual(t, executed, true)
})
})
t.Run("should call the user provided behavior correctly", func(t *testing.T) {
t.Run("Insert", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
table ksql.Table
record interface{}
}
mock := ksql.Mock{
InsertFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
capturedArgs.ctx = ctx
capturedArgs.table = table
capturedArgs.record = record
return fmt.Errorf("fake-error")
},
}
err := mock.Insert(ctx, UsersTable, &User{
Name: "fake-name",
Age: 42,
})
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.table, UsersTable)
tt.AssertEqual(t, capturedArgs.record, &User{
Name: "fake-name",
Age: 42,
})
})
t.Run("Patch", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
table ksql.Table
record interface{}
}
mock := ksql.Mock{
PatchFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
capturedArgs.ctx = ctx
capturedArgs.table = table
capturedArgs.record = record
return fmt.Errorf("fake-error")
},
}
err := mock.Patch(ctx, UsersTable, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.table, UsersTable)
tt.AssertEqual(t, capturedArgs.record, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
})
t.Run("Delete", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
table ksql.Table
record interface{}
}
mock := ksql.Mock{
DeleteFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
capturedArgs.ctx = ctx
capturedArgs.table = table
capturedArgs.record = record
return fmt.Errorf("fake-error")
},
}
err := mock.Delete(ctx, UsersTable, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.table, UsersTable)
tt.AssertEqual(t, capturedArgs.record, &User{
ID: 4242,
Name: "fake-name",
Age: 42,
})
})
t.Run("Query", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
records interface{}
query string
params []interface{}
}
mock := ksql.Mock{
QueryFn: func(ctx context.Context, records interface{}, query string, params ...interface{}) error {
capturedArgs.ctx = ctx
capturedArgs.records = records
capturedArgs.query = query
capturedArgs.params = params
return fmt.Errorf("fake-error")
},
}
var users []User
err := mock.Query(ctx, &users, "SELECT * FROM user WHERE age = ?", 42)
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.records, &users)
tt.AssertEqual(t, capturedArgs.query, "SELECT * FROM user WHERE age = ?")
tt.AssertEqual(t, capturedArgs.params, []interface{}{42})
})
t.Run("QueryOne", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
record interface{}
query string
params []interface{}
}
mock := ksql.Mock{
QueryOneFn: func(ctx context.Context, record interface{}, query string, params ...interface{}) error {
capturedArgs.ctx = ctx
capturedArgs.record = record
capturedArgs.query = query
capturedArgs.params = params
return fmt.Errorf("fake-error")
},
}
var user User
err := mock.QueryOne(ctx, &user, "SELECT * FROM user WHERE id = ?", 4242)
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.record, &user)
tt.AssertEqual(t, capturedArgs.query, "SELECT * FROM user WHERE id = ?")
tt.AssertEqual(t, capturedArgs.params, []interface{}{4242})
})
t.Run("QueryChunks", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
parser ksql.ChunkParser
}
mock := ksql.Mock{
QueryChunksFn: func(ctx context.Context, parser ksql.ChunkParser) error {
capturedArgs.ctx = ctx
capturedArgs.parser = parser
return fmt.Errorf("fake-error")
},
}
var users []User
chunkParserFunc := func(chunk []User) error {
users = append(users, chunk...)
return nil
}
err := mock.QueryChunks(ctx, ksql.ChunkParser{
Query: "SELECT * FROM users WHERE age = ?",
Params: []interface{}{
4242,
},
ChunkSize: 10,
ForEachChunk: chunkParserFunc,
})
tt.AssertErrContains(t, err, "fake-error")
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.parser.Query, "SELECT * FROM users WHERE age = ?")
tt.AssertEqual(t, capturedArgs.parser.Params, []interface{}{
4242,
})
tt.AssertEqual(t, capturedArgs.parser.ChunkSize, 10)
})
t.Run("Exec", func(t *testing.T) {
ctx := context.Background()
var capturedArgs struct {
ctx context.Context
query string
params []interface{}
}
mock := ksql.Mock{
ExecFn: func(ctx context.Context, query string, params ...interface{}) (ksql.Result, error) {
capturedArgs.ctx = ctx
capturedArgs.query = query
capturedArgs.params = params
return ksql.NewMockResult(42, 42), fmt.Errorf("fake-error")
},
}
r, err := mock.Exec(ctx, "INSERT INTO users_permissions(user_id, permission_id) VALUES (?, ?)", 4242, 4)
tt.AssertErrContains(t, err, "fake-error")
rowsAffected, err := r.RowsAffected()
tt.AssertNoErr(t, err)
tt.AssertEqual(t, rowsAffected, int64(42))
lastInsertID, err := r.LastInsertId()
tt.AssertNoErr(t, err)
tt.AssertEqual(t, lastInsertID, int64(42))
tt.AssertEqual(t, capturedArgs.ctx, ctx)
tt.AssertEqual(t, capturedArgs.query, "INSERT INTO users_permissions(user_id, permission_id) VALUES (?, ?)")
tt.AssertEqual(t, capturedArgs.params, []interface{}{4242, 4})
})
t.Run("Transaction", func(t *testing.T) {
ctx := context.Background()
executingMockedTransaction := false
mock := ksql.Mock{
TransactionFn: func(ctx context.Context, fn func(db ksql.Provider) error) error {
executingMockedTransaction = true
return nil
},
}
executed := false
mock.Transaction(ctx, func(db ksql.Provider) error {
executed = true
return nil
})
tt.AssertEqual(t, executingMockedTransaction, true)
tt.AssertEqual(t, executed, false)
})
})
t.Run("SetFallbackDatabase", func(t *testing.T) {
testMock := ksql.Mock{}
dbMock := ksql.Mock{
InsertFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
return fmt.Errorf("called from InsertFn")
},
PatchFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
return fmt.Errorf("called from PatchFn")
},
DeleteFn: func(ctx context.Context, table ksql.Table, record interface{}) error {
return fmt.Errorf("called from DeleteFn")
},
QueryFn: func(ctx context.Context, records interface{}, query string, params ...interface{}) error {
return fmt.Errorf("called from QueryFn")
},
QueryOneFn: func(ctx context.Context, record interface{}, query string, params ...interface{}) error {
return fmt.Errorf("called from QueryOneFn")
},
QueryChunksFn: func(ctx context.Context, parser ksql.ChunkParser) error {
return fmt.Errorf("called from QueryChunksFn")
},
ExecFn: func(ctx context.Context, query string, params ...interface{}) (ksql.Result, error) {
return nil, fmt.Errorf("called from ExecFn")
},
TransactionFn: func(ctx context.Context, fn func(db ksql.Provider) error) error {
return fmt.Errorf("called from TransactionFn")
},
}
ctx := context.Background()
testMock = testMock.SetFallbackDatabase(dbMock)
var user User
err := testMock.Insert(ctx, UsersTable, &user)
tt.AssertErrContains(t, err, "called from InsertFn")
err = testMock.Patch(ctx, UsersTable, &user)
tt.AssertErrContains(t, err, "called from PatchFn")
err = testMock.Delete(ctx, UsersTable, &user)
tt.AssertErrContains(t, err, "called from DeleteFn")
var users []User
err = testMock.Query(ctx, &users, "fake-query")
tt.AssertErrContains(t, err, "called from QueryFn")
err = testMock.QueryOne(ctx, &user, "fake-query")
tt.AssertErrContains(t, err, "called from QueryOneFn")
err = testMock.QueryChunks(ctx, ksql.ChunkParser{})
tt.AssertErrContains(t, err, "called from QueryChunksFn")
_, err = testMock.Exec(ctx, "fake-query")
tt.AssertErrContains(t, err, "called from ExecFn")
err = testMock.Transaction(ctx, func(db ksql.Provider) error {
return nil
})
tt.AssertErrContains(t, err, "called from TransactionFn")
})
}
func TestMockResult(t *testing.T) {
t.Run("LastInsertId", func(t *testing.T) {
t.Run("the constructor should work correctly", func(t *testing.T) {
result := ksql.NewMockResult(24, 42)
lastInsertID, err := result.LastInsertId()
tt.AssertNoErr(t, err)
tt.AssertEqual(t, lastInsertID, int64(24))
})
t.Run("should panic if no values are provided", func(t *testing.T) {
result := ksql.MockResult{}
panicPayload := tt.PanicHandler(func() {
result.LastInsertId()
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.MockResult.LastInsertId(", "ksql.MockResult.LastInsertIdFn", "not set")
})
})
t.Run("RowsAffected", func(t *testing.T) {
t.Run("the constructor should work correctly", func(t *testing.T) {
result := ksql.NewMockResult(24, 42)
rowsAffected, err := result.RowsAffected()
tt.AssertNoErr(t, err)
tt.AssertEqual(t, rowsAffected, int64(42))
})
t.Run("should panic if no values are provided", func(t *testing.T) {
result := ksql.MockResult{}
panicPayload := tt.PanicHandler(func() {
result.RowsAffected()
})
err, ok := panicPayload.(error)
tt.AssertEqual(t, ok, true)
tt.AssertErrContains(t, err, "ksql.MockResult.RowsAffected(", "ksql.MockResult.RowsAffectedFn", "not set")
})
})
}