Skip to content

Commit

Permalink
Generic test repository wrapper (#52)
Browse files Browse the repository at this point in the history
* Generic type Repository mock wrapper

* replace interface with any

* refactor record to entity

* use wrap transaction
  • Loading branch information
Fs02 authored Oct 23, 2022
1 parent 3c2850f commit e57942c
Show file tree
Hide file tree
Showing 53 changed files with 1,036 additions and 370 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ jobs:
name: Build
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
go: [1.12, 1.13, 1.4, 1.15, 1.16]
os: [ubuntu-latest]
go: [1.15, 1.16, 1.17, 1.18, 1.19]
runs-on: ${{ matrix.os }}
steps:
- name: Set up Go 1.x
Expand All @@ -26,7 +26,7 @@ jobs:
run: go test -race ./...
- name: Coverage
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...
if: matrix.go == 1.16 && matrix.os == 'ubuntu-latest'
if: matrix.go == 1.19 && matrix.os == 'ubuntu-latest'
- name: Codecov
uses: codecov/codecov-action@v1
if: matrix.go == 1.16 && matrix.os == 'ubuntu-latest'
if: matrix.go == 1.19 && matrix.os == 'ubuntu-latest'
2 changes: 1 addition & 1 deletion aggregate.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (a aggregate) execute(ctx context.Context, query rel.Query, aggregate strin
panic(failExecuteMessage(ma, a))
}

func (a *aggregate) assert(t T) bool {
func (a *aggregate) assert(t TestingT) bool {
t.Helper()
for _, ma := range *a {
if !ma.assert.assert(t, ma) {
Expand Down
6 changes: 6 additions & 0 deletions any_notgo1.18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//go:build !go118
// +build !go118

package reltest

type any = interface{}
14 changes: 7 additions & 7 deletions assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"reflect"
)

// T is an interface wrapper around *testing.T
type T interface {
Logf(format string, args ...interface{})
Errorf(format string, args ...interface{})
// TestingT is an interface wrapper around *testing.T
type TestingT interface {
Logf(format string, args ...any)
Errorf(format string, args ...any)
Helper()
}

Expand Down Expand Up @@ -56,7 +56,7 @@ func (a *Assert) call(ctx context.Context) bool {
return true
}

func (a Assert) assert(t T, mock interface{}) bool {
func (a Assert) assert(t TestingT, mock any) bool {
if a.optional ||
(a.repeatability == 0 && a.totalCalls > 0) ||
(a.repeatability != 0 && a.totalCalls >= a.repeatability) {
Expand All @@ -73,14 +73,14 @@ func (a Assert) assert(t T, mock interface{}) bool {
return false
}

func (a Assert) sprintf(format string, args ...interface{}) string {
func (a Assert) sprintf(format string, args ...any) string {
if a.ctxData.txDepth != 0 {
return a.ctxData.String() + " " + fmt.Sprintf(format, args...)
}
return fmt.Sprintf(format, args...)
}

func failExecuteMessage(call interface{}, mocks interface{}) string {
func failExecuteMessage(call any, mocks any) string {
var (
mocksStr string
callStr = call.(interface{ String() string }).String()
Expand Down
4 changes: 2 additions & 2 deletions assert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ type noopt struct {
lastLog string
}

func (t *noopt) Logf(format string, args ...interface{}) {
func (t *noopt) Logf(format string, args ...any) {
t.lastLog = fmt.Sprintf(format, args...)
}

func (t *noopt) Errorf(format string, args ...interface{}) {
func (t *noopt) Errorf(format string, args ...any) {
t.lastLog = fmt.Sprintf(format, args...)
}

Expand Down
2 changes: 1 addition & 1 deletion count.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (c count) execute(ctx context.Context, collection string, queriers ...rel.Q
panic(failExecuteMessage(mc, c))
}

func (c *count) assert(t T) bool {
func (c *count) assert(t TestingT) bool {
t.Helper()
for _, mc := range *c {
if !mc.assert.assert(t, mc) {
Expand Down
58 changes: 29 additions & 29 deletions delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ func (d *delete) register(ctxData ctxData, mutators ...rel.Mutator) *MockDelete
return md
}

func (d delete) execute(ctx context.Context, record interface{}, mutators ...rel.Mutator) error {
func (d delete) execute(ctx context.Context, entity any, mutators ...rel.Mutator) error {
for _, md := range d {
if (md.argRecord == nil || reflect.DeepEqual(md.argRecord, record)) &&
(md.argRecordType == "" || md.argRecordType == reflect.TypeOf(record).String()) &&
(md.argRecordTable == "" || md.argRecordTable == rel.NewDocument(record, true).Table()) &&
(md.argRecordContains == nil || matchContains(md.argRecordContains, record)) &&
if (md.argEntity == nil || reflect.DeepEqual(md.argEntity, entity)) &&
(md.argEntityType == "" || md.argEntityType == reflect.TypeOf(entity).String()) &&
(md.argEntityTable == "" || md.argEntityTable == rel.NewDocument(entity, true).Table()) &&
(md.argEntityContains == nil || matchContains(md.argEntityContains, entity)) &&
matchMutators(md.argMutators, mutators) &&
md.assert.call(ctx) {
return md.retError
Expand All @@ -34,14 +34,14 @@ func (d delete) execute(ctx context.Context, record interface{}, mutators ...rel

md := &MockDelete{
assert: &Assert{ctxData: fetchContext(ctx)},
argRecord: record,
argEntity: entity,
argMutators: mutators,
}

panic(failExecuteMessage(md, d))
}

func (d *delete) assert(t T) bool {
func (d *delete) assert(t TestingT) bool {
t.Helper()
for _, md := range *d {
if !md.assert.assert(t, md) {
Expand All @@ -56,36 +56,36 @@ func (d *delete) assert(t T) bool {
// MockDelete asserts and simulate Delete function for test.
type MockDelete struct {
assert *Assert
argRecord interface{}
argRecordType string
argRecordTable string
argRecordContains interface{}
argEntity any
argEntityType string
argEntityTable string
argEntityContains any
argMutators []rel.Mutator
retError error
}

// For assert calls for given record.
func (md *MockDelete) For(record interface{}) *MockDelete {
md.argRecord = record
// For assert calls for given entity.
func (md *MockDelete) For(entity any) *MockDelete {
md.argEntity = entity
return md
}

// ForType assert calls for given type.
// Type must include package name, example: `model.User`.
func (md *MockDelete) ForType(typ string) *MockDelete {
md.argRecordType = "*" + strings.TrimPrefix(typ, "*")
md.argEntityType = "*" + strings.TrimPrefix(typ, "*")
return md
}

// ForTable assert calls for given table.
func (md *MockDelete) ForTable(typ string) *MockDelete {
md.argRecordTable = typ
md.argEntityTable = typ
return md
}

// ForContains assert calls to contains some value of given struct.
func (md *MockDelete) ForContains(contains interface{}) *MockDelete {
md.argRecordContains = contains
func (md *MockDelete) ForContains(contains any) *MockDelete {
md.argEntityContains = contains
return md
}

Expand All @@ -107,23 +107,23 @@ func (md *MockDelete) ConnectionClosed() *Assert {

// String representation of mocked call.
func (md MockDelete) String() string {
argRecord := "<Any>"
if md.argRecord != nil {
argRecord = csprint(md.argRecord, true)
} else if md.argRecordContains != nil {
argRecord = fmt.Sprintf("<Contains: %s>", csprint(md.argRecordContains, true))
} else if md.argRecordType != "" {
argRecord = fmt.Sprintf("<Type: %s>", md.argRecordType)
} else if md.argRecordTable != "" {
argRecord = fmt.Sprintf("<Table: %s>", md.argRecordTable)
argEntity := "<Any>"
if md.argEntity != nil {
argEntity = csprint(md.argEntity, true)
} else if md.argEntityContains != nil {
argEntity = fmt.Sprintf("<Contains: %s>", csprint(md.argEntityContains, true))
} else if md.argEntityType != "" {
argEntity = fmt.Sprintf("<Type: %s>", md.argEntityType)
} else if md.argEntityTable != "" {
argEntity = fmt.Sprintf("<Table: %s>", md.argEntityTable)
}

argMutators := ""
for i := range md.argMutators {
argMutators += fmt.Sprintf(", %v", md.argMutators[i])
}

return md.assert.sprintf("Delete(ctx, %s%s)", argRecord, argMutators)
return md.assert.sprintf("Delete(ctx, %s%s)", argEntity, argMutators)
}

// ExpectString representation of mocked call.
Expand All @@ -133,5 +133,5 @@ func (md MockDelete) ExpectString() string {
argMutators += fmt.Sprintf("%v", md.argMutators[i])
}

return md.assert.sprintf("ExpectDelete(%s).ForType(\"%T\")", argMutators, md.argRecord)
return md.assert.sprintf("ExpectDelete(%s).ForType(\"%T\")", argMutators, md.argEntity)
}
46 changes: 23 additions & 23 deletions delete_all.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,24 @@ func (da *deleteAll) register(ctxData ctxData) *MockDeleteAll {
return mda
}

func (da deleteAll) execute(ctx context.Context, record interface{}) error {
func (da deleteAll) execute(ctx context.Context, entity any) error {
for _, mda := range da {
if (mda.argRecord == nil || reflect.DeepEqual(mda.argRecord, record)) &&
(mda.argRecordType == "" || mda.argRecordType == reflect.TypeOf(record).String()) &&
(mda.argRecordTable == "" || mda.argRecordTable == rel.NewCollection(record, true).Table()) &&
if (mda.argEntity == nil || reflect.DeepEqual(mda.argEntity, entity)) &&
(mda.argEntityType == "" || mda.argEntityType == reflect.TypeOf(entity).String()) &&
(mda.argEntityTable == "" || mda.argEntityTable == rel.NewCollection(entity, true).Table()) &&
mda.assert.call(ctx) {
return mda.retError
}
}

mda := &MockDeleteAll{
assert: &Assert{ctxData: fetchContext(ctx)},
argRecord: record,
argEntity: entity,
}
panic(failExecuteMessage(mda, da))
}

func (da *deleteAll) assert(t T) bool {
func (da *deleteAll) assert(t TestingT) bool {
t.Helper()
for _, mda := range *da {
if !mda.assert.assert(t, mda) {
Expand All @@ -51,28 +51,28 @@ func (da *deleteAll) assert(t T) bool {
// MockDeleteAll asserts and simulate Delete function for test.
type MockDeleteAll struct {
assert *Assert
argRecord interface{}
argRecordType string
argRecordTable string
argEntity any
argEntityType string
argEntityTable string
retError error
}

// For assert calls for given record.
func (mda *MockDeleteAll) For(record interface{}) *MockDeleteAll {
mda.argRecord = record
// For assert calls for given entity.
func (mda *MockDeleteAll) For(entity any) *MockDeleteAll {
mda.argEntity = entity
return mda
}

// ForType assert calls for given type.
// Type must include package name, example: `model.User`.
func (mda *MockDeleteAll) ForType(typ string) *MockDeleteAll {
mda.argRecordType = "*" + strings.TrimPrefix(typ, "*")
mda.argEntityType = "*" + strings.TrimPrefix(typ, "*")
return mda
}

// ForTable assert calls for given table.
func (mda *MockDeleteAll) ForTable(typ string) *MockDeleteAll {
mda.argRecordTable = typ
mda.argEntityTable = typ
return mda
}

Expand All @@ -94,19 +94,19 @@ func (mda *MockDeleteAll) ConnectionClosed() *Assert {

// String representation of mocked call.
func (mda MockDeleteAll) String() string {
argRecord := "<Any>"
if mda.argRecord != nil {
argRecord = csprint(mda.argRecord, true)
} else if mda.argRecordType != "" {
argRecord = fmt.Sprintf("<Type: %s>", mda.argRecordType)
} else if mda.argRecordTable != "" {
argRecord = fmt.Sprintf("<Table: %s>", mda.argRecordTable)
argEntity := "<Any>"
if mda.argEntity != nil {
argEntity = csprint(mda.argEntity, true)
} else if mda.argEntityType != "" {
argEntity = fmt.Sprintf("<Type: %s>", mda.argEntityType)
} else if mda.argEntityTable != "" {
argEntity = fmt.Sprintf("<Table: %s>", mda.argEntityTable)
}

return mda.assert.sprintf("DeleteAll(ctx, %s)", argRecord)
return mda.assert.sprintf("DeleteAll(ctx, %s)", argEntity)
}

// ExpectString representation of mocked call.
func (mda MockDeleteAll) ExpectString() string {
return mda.assert.sprintf(`ExpectDeleteAll().ForType("%T")`, mda.argRecord)
return mda.assert.sprintf(`ExpectDeleteAll().ForType("%T")`, mda.argEntity)
}
2 changes: 1 addition & 1 deletion delete_all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ func TestDeleteAll_assert_transaction(t *testing.T) {

func TestDeleteAll_String(t *testing.T) {
var (
mockDeleteAll = MockDeleteAll{assert: &Assert{}, argRecord: &[]Book{}}
mockDeleteAll = MockDeleteAll{assert: &Assert{}, argEntity: &[]Book{}}
)

assert.Equal(t, `DeleteAll(ctx, &[]reltest.Book{})`, mockDeleteAll.String())
Expand Down
6 changes: 3 additions & 3 deletions delete_any.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (da deleteAny) execute(ctx context.Context, query rel.Query) (int, error) {
}

if !mda.unsafe && query.WhereQuery.None() {
panic("reltest: unsafe DeleteAny detected. if you want to mutate all records without filter, please use call .Unsafe()")
panic("reltest: unsafe DeleteAny detected. if you want to mutate all entities without filter, please use call .Unsafe()")
}

return mda.retDeletedCount, mda.retError
Expand All @@ -40,7 +40,7 @@ func (da deleteAny) execute(ctx context.Context, query rel.Query) (int, error) {
panic(failExecuteMessage(mda, da))
}

func (da *deleteAny) assert(t T) bool {
func (da *deleteAny) assert(t TestingT) bool {
t.Helper()
for _, mda := range *da {
if !mda.assert.assert(t, mda) {
Expand All @@ -61,7 +61,7 @@ type MockDeleteAny struct {
retError error
}

// Unsafe allows for unsafe operation to delete records without where condition.
// Unsafe allows for unsafe operation to delete entities without where condition.
func (mda *MockDeleteAny) Unsafe() *MockDeleteAny {
mda.unsafe = true
return mda
Expand Down
2 changes: 1 addition & 1 deletion delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func TestDelete_assert_transaction(t *testing.T) {

func TestDelete_String(t *testing.T) {
var (
mockDelete = MockDelete{assert: &Assert{}, argRecord: &Book{}}
mockDelete = MockDelete{assert: &Assert{}, argEntity: &Book{}}
)

assert.Equal(t, "Delete(ctx, &reltest.Book{})", mockDelete.String())
Expand Down
15 changes: 15 additions & 0 deletions entity_delete_all_go1.18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build go1.18
// +build go1.18

package reltest

// EntityMockDeleteAll mock wrapper
type EntityMockDeleteAll[T any] struct {
*MockDeleteAll
}

// For assert calls for given entity.
func (emda *EntityMockDeleteAll[T]) For(result *[]T) *EntityMockDeleteAll[T] {
emda.MockDeleteAll.For(result)
return emda
}
Loading

0 comments on commit e57942c

Please sign in to comment.