diff --git a/go.mod b/go.mod index 546d7e3d..cb92fa5a 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/go-rel/rel require ( - github.com/go-rel/reltest v0.5.0 + github.com/go-rel/reltest v0.6.0 github.com/jinzhu/inflection v1.0.0 github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e github.com/stretchr/testify v1.7.0 diff --git a/go.sum b/go.sum index 463434a4..deece817 100644 --- a/go.sum +++ b/go.sum @@ -5,9 +5,11 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-rel/rel v0.28.0/go.mod h1:zaIYPmM3AfJrh0xBmm7KoVKRgTNvr0cgZfcJ88gVA2U= github.com/go-rel/rel v0.30.0/go.mod h1:Wu6HB6x0oIiEOdUJClwmn7ByCmdL73U5gItAYObyyuo= +github.com/go-rel/rel v0.31.0/go.mod h1:fCMlDiwDSSBSoZQ6ovUyjSqS2FfpLnhwr6tW9TgnhC8= github.com/go-rel/reltest v0.4.0/go.mod h1:3udgrKCZGCMFWc8k+RH975gUdUFPE/yspG2iWN9gjqU= -github.com/go-rel/reltest v0.5.0 h1:ReQzqu538lK9HU8/RKv3Z5e2WnycsAJlVL2ippDckQU= github.com/go-rel/reltest v0.5.0/go.mod h1:onixPXWMVL+KILH7OdUufKDm1KN0H6FzXOP7OoNC9qM= +github.com/go-rel/reltest v0.6.0 h1:mzF49w6jo1eyvfbpogL6BvxCuJrMwsjD+49qI9gCyEs= +github.com/go-rel/reltest v0.6.0/go.mod h1:4jR+L2vn7qe6NDW1carPomp2SlbTsQ9dqkxC+n4db+k= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= diff --git a/reltest/aggregate.go b/reltest/aggregate.go deleted file mode 100644 index c9b79d6a..00000000 --- a/reltest/aggregate.go +++ /dev/null @@ -1,43 +0,0 @@ -package reltest - -import "github.com/go-rel/rel" - -// Aggregate asserts and simulate aggregate function for test. -type Aggregate struct { - *Expect -} - -// Result sets the result of this query. -func (a *Aggregate) Result(count int) { - a.Return(count, nil) -} - -// Error sets error to be returned. -func (a *Aggregate) Error(err error) { - a.Return(0, err) -} - -// ConnectionClosed sets this error to be returned. -func (a *Aggregate) ConnectionClosed() { - a.Error(ErrConnectionClosed) -} - -// ExpectAggregate to be called with given field and queries. -func ExpectAggregate(r *Repository, query rel.Query, aggregate string, field string) *Aggregate { - return &Aggregate{ - Expect: newExpect(r, "Aggregate", - []interface{}{r.ctxData, query, aggregate, field}, - []interface{}{0, nil}, - ), - } -} - -// ExpectCount to be called with given field and queries. -func ExpectCount(r *Repository, collection string, queriers []rel.Querier) *Aggregate { - return &Aggregate{ - Expect: newExpect(r, "Count", - []interface{}{r.ctxData, collection, queriers}, - []interface{}{0, nil}, - ), - } -} diff --git a/reltest/aggregate_test.go b/reltest/aggregate_test.go deleted file mode 100644 index 7c6c11ad..00000000 --- a/reltest/aggregate_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/assert" -) - -func TestAggregate(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectAggregate(rel.From("books"), "sum", "id").Result(3) - sum, err := repo.Aggregate(context.TODO(), rel.From("books"), "sum", "id") - assert.Nil(t, err) - assert.Equal(t, 3, sum) - repo.AssertExpectations(t) - - repo.ExpectAggregate(rel.From("books"), "sum", "id").Result(3) - assert.NotPanics(t, func() { - sum := repo.MustAggregate(context.TODO(), rel.From("books"), "sum", "id") - assert.Equal(t, 3, sum) - }) - repo.AssertExpectations(t) -} - -func TestAggregate_error(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectAggregate(rel.From("books"), "sum", "id").ConnectionClosed() - sum, err := repo.Aggregate(context.TODO(), rel.From("books"), "sum", "id") - assert.Equal(t, sql.ErrConnDone, err) - assert.Equal(t, 0, sum) - repo.AssertExpectations(t) - - repo.ExpectAggregate(rel.From("books"), "sum", "id").ConnectionClosed() - assert.Panics(t, func() { - sum := repo.MustAggregate(context.TODO(), rel.From("books"), "sum", "id") - assert.Equal(t, 0, sum) - }) - repo.AssertExpectations(t) -} - -func TestAggregate_Count(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectCount("books").Result(2) - count, err := repo.Count(context.TODO(), "books") - assert.Nil(t, err) - assert.Equal(t, 2, count) - repo.AssertExpectations(t) - - repo.ExpectCount("books").Result(2) - assert.NotPanics(t, func() { - count := repo.MustCount(context.TODO(), "books") - assert.Equal(t, 2, count) - }) - repo.AssertExpectations(t) -} - -func TestAggregate_Count_error(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectCount("books").ConnectionClosed() - count, err := repo.Count(context.TODO(), "books") - assert.Equal(t, sql.ErrConnDone, err) - assert.Equal(t, 0, count) - repo.AssertExpectations(t) - - repo.ExpectCount("books").ConnectionClosed() - assert.Panics(t, func() { - count := repo.MustCount(context.TODO(), "books") - assert.Equal(t, 0, count) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/context.go b/reltest/context.go deleted file mode 100644 index d413e9cf..00000000 --- a/reltest/context.go +++ /dev/null @@ -1,27 +0,0 @@ -package reltest - -import ( - "context" -) - -type ctxKeyType uint8 - -type ctxData struct { - txDepth int -} - -var ( - ctxKey ctxKeyType = 0 -) - -func fetchContext(ctx context.Context) ctxData { - if tx, ok := ctx.Value(ctxKey).(ctxData); ok { - return tx - } - - return ctxData{} -} - -func wrapContext(ctx context.Context, ctxData ctxData) context.Context { - return context.WithValue(ctx, ctxKey, ctxData) -} diff --git a/reltest/delete.go b/reltest/delete.go deleted file mode 100644 index 41d771f0..00000000 --- a/reltest/delete.go +++ /dev/null @@ -1,39 +0,0 @@ -package reltest - -import ( - "strings" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// Delete asserts and simulate delete function for test. -type Delete struct { - *Expect -} - -// For match expect calls for given record. -func (d *Delete) For(record interface{}) *Delete { - d.Arguments[1] = record - return d -} - -// ForType match expect calls for given type. -// Type must include package name, example: `model.User`. -func (d *Delete) ForType(typ string) *Delete { - return d.For(mock.AnythingOfType("*" + strings.TrimPrefix(typ, "*"))) -} - -// ExpectDelete to be called. -func ExpectDelete(r *Repository, options []rel.Cascade) *Delete { - return &Delete{ - Expect: newExpect(r, "Delete", []interface{}{r.ctxData, mock.Anything, options}, []interface{}{nil}), - } -} - -// ExpectDeleteAll to be called. -func ExpectDeleteAll(r *Repository) *Delete { - return &Delete{ - Expect: newExpect(r, "DeleteAll", []interface{}{r.ctxData, mock.Anything}, []interface{}{nil}), - } -} diff --git a/reltest/delete_test.go b/reltest/delete_test.go deleted file mode 100644 index eba14d00..00000000 --- a/reltest/delete_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestDelete(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDelete().For(&Book{ID: 1}) - assert.Nil(t, repo.Delete(context.TODO(), &Book{ID: 1})) - repo.AssertExpectations(t) - - repo.ExpectDelete().For(&Book{ID: 1}) - assert.NotPanics(t, func() { - repo.MustDelete(context.TODO(), &Book{ID: 1}) - }) - repo.AssertExpectations(t) -} - -func TestDelete_forType(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDelete().ForType("reltest.Book") - assert.Nil(t, repo.Delete(context.TODO(), &Book{ID: 1})) - repo.AssertExpectations(t) - - repo.ExpectDelete().ForType("reltest.Book") - assert.NotPanics(t, func() { - repo.MustDelete(context.TODO(), &Book{ID: 1}) - }) - repo.AssertExpectations(t) -} - -func TestDelete_error(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDelete().ConnectionClosed() - assert.Equal(t, sql.ErrConnDone, repo.Delete(context.TODO(), &Book{ID: 1})) - repo.AssertExpectations(t) - - repo.ExpectDelete().ConnectionClosed() - assert.Panics(t, func() { - repo.MustDelete(context.TODO(), &Book{ID: 1}) - }) - repo.AssertExpectations(t) -} - -func TestDeleteAll(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDeleteAll().For(&[]Book{{ID: 1}}) - assert.Nil(t, repo.DeleteAll(context.TODO(), &[]Book{{ID: 1}})) - repo.AssertExpectations(t) - - repo.ExpectDeleteAll().For(&[]Book{{ID: 1}}) - assert.NotPanics(t, func() { - repo.MustDeleteAll(context.TODO(), &[]Book{{ID: 1}}) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/exec.go b/reltest/exec.go deleted file mode 100644 index 0f60c5dc..00000000 --- a/reltest/exec.go +++ /dev/null @@ -1,31 +0,0 @@ -package reltest - -// Exec asserts and simulate exec function for test. -type Exec struct { - *Expect -} - -// Result sets the result of this query. -func (e *Exec) Result(lastInsertedId int, rowsAffected int) { - e.Return(lastInsertedId, rowsAffected, nil) -} - -// Error sets error to be returned. -func (e *Exec) Error(err error) { - e.Return(0, 0, err) -} - -// ConnectionClosed sets this error to be returned. -func (e *Exec) ConnectionClosed() { - e.Error(ErrConnectionClosed) -} - -// ExpectExec to be called with given field and queries. -func ExpectExec(r *Repository, statement string, args []interface{}) *Exec { - return &Exec{ - Expect: newExpect(r, "Exec", - []interface{}{r.ctxData, statement, args}, - []interface{}{0, 0, nil}, - ), - } -} diff --git a/reltest/exec_test.go b/reltest/exec_test.go deleted file mode 100644 index 4dd4f3ba..00000000 --- a/reltest/exec_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestExec(t *testing.T) { - var ( - repo = New() - statement = "UPDATE users SET something = ? WHERE something2 = ?;" - args = []interface{}{1, "2"} - ) - - repo.ExpectExec(statement, args).Result(1, 2) - lastInsertedId, rowsAffected, err := repo.Exec(context.TODO(), statement, args...) - assert.Nil(t, err) - assert.Equal(t, 1, lastInsertedId) - assert.Equal(t, 2, rowsAffected) - repo.AssertExpectations(t) - - repo.ExpectExec(statement, args).Result(1, 2) - assert.NotPanics(t, func() { - lastInsertedId, rowsAffected := repo.MustExec(context.TODO(), statement, args...) - assert.Equal(t, 1, lastInsertedId) - assert.Equal(t, 2, rowsAffected) - }) - repo.AssertExpectations(t) -} - -func TestExec_error(t *testing.T) { - var ( - repo = New() - statement = "UPDATE users SET something = ? WHERE something2 = ?;" - args = []interface{}{1, "2"} - ) - - repo.ExpectExec(statement, args).ConnectionClosed() - lastInsertedId, rowsAffected, err := repo.Exec(context.TODO(), statement, args...) - assert.Equal(t, sql.ErrConnDone, err) - assert.Equal(t, 0, lastInsertedId) - assert.Equal(t, 0, rowsAffected) - repo.AssertExpectations(t) - - repo.ExpectExec(statement, args).ConnectionClosed() - assert.Panics(t, func() { - repo.MustExec(context.TODO(), statement, args...) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/expect.go b/reltest/expect.go deleted file mode 100644 index 1969296a..00000000 --- a/reltest/expect.go +++ /dev/null @@ -1,33 +0,0 @@ -package reltest - -import ( - "database/sql" - - "github.com/stretchr/testify/mock" -) - -var ( - // ErrConnectionClosed is alias for sql.ErrConnDone. - ErrConnectionClosed = sql.ErrConnDone -) - -// Expect is base behaviour for all reltest expectations. -type Expect struct { - *mock.Call -} - -// Error sets error to be returned. -func (e *Expect) Error(err error) { - e.Return(err) -} - -// ConnectionClosed sets this error to be returned. -func (e *Expect) ConnectionClosed() { - e.Error(ErrConnectionClosed) -} - -func newExpect(r *Repository, methodName string, args []interface{}, rets []interface{}) *Expect { - return &Expect{ - Call: r.mock.On(methodName, args...).Return(rets...).Once(), - } -} diff --git a/reltest/find.go b/reltest/find.go deleted file mode 100644 index a8e1fd05..00000000 --- a/reltest/find.go +++ /dev/null @@ -1,28 +0,0 @@ -package reltest - -import ( - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// Find asserts and simulate find function for test. -type Find struct { - *FindAll -} - -// NotFound sets NotFoundError to be returned. -func (f *Find) NotFound() { - f.Error(rel.NotFoundError{}) -} - -// ExpectFind to be called with given field and queries. -func ExpectFind(r *Repository, queriers []rel.Querier) *Find { - return &Find{ - FindAll: &FindAll{ - Expect: newExpect(r, "Find", - []interface{}{r.ctxData, mock.Anything, queriers}, - []interface{}{nil}, - ), - }, - } -} diff --git a/reltest/find_all.go b/reltest/find_all.go deleted file mode 100644 index 4beb26e9..00000000 --- a/reltest/find_all.go +++ /dev/null @@ -1,33 +0,0 @@ -package reltest - -import ( - "fmt" - "reflect" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// FindAll asserts and simulate find all function for test. -type FindAll struct { - *Expect -} - -// Result sets the result of this query. -func (fa *FindAll) Result(records interface{}) { - fa.Arguments[1] = mock.AnythingOfType(fmt.Sprintf("*%T", records)) - - fa.Run(func(args mock.Arguments) { - reflect.ValueOf(args[1]).Elem().Set(reflect.ValueOf(records)) - }) -} - -// ExpectFindAll to be called with given field and queries. -func ExpectFindAll(r *Repository, queriers []rel.Querier) *FindAll { - return &FindAll{ - Expect: newExpect(r, "FindAll", - []interface{}{r.ctxData, mock.Anything, queriers}, - []interface{}{nil}, - ), - } -} diff --git a/reltest/find_all_test.go b/reltest/find_all_test.go deleted file mode 100644 index fe316d04..00000000 --- a/reltest/find_all_test.go +++ /dev/null @@ -1,56 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/go-rel/rel/where" - "github.com/stretchr/testify/assert" -) - -func TestFindAll(t *testing.T) { - var ( - repo = New() - result []Book - books = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - ) - - repo.ExpectFindAll(where.Like("title", "%dummies%")).Result(books) - assert.Nil(t, repo.FindAll(context.TODO(), &result, where.Like("title", "%dummies%"))) - assert.Equal(t, books, result) - repo.AssertExpectations(t) - - repo.ExpectFindAll(where.Like("title", "%dummies%")).Result(books) - assert.NotPanics(t, func() { - repo.MustFindAll(context.TODO(), &result, where.Like("title", "%dummies%")) - assert.Equal(t, books, result) - }) - repo.AssertExpectations(t) -} - -func TestFindAll_error(t *testing.T) { - var ( - repo = New() - result []Book - books = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - ) - - repo.ExpectFindAll(where.Like("title", "%dummies%")).ConnectionClosed() - assert.Equal(t, sql.ErrConnDone, repo.FindAll(context.TODO(), &result, where.Like("title", "%dummies%"))) - assert.NotEqual(t, books, result) - repo.AssertExpectations(t) - - repo.ExpectFindAll(where.Like("title", "%dummies%")).ConnectionClosed() - assert.Panics(t, func() { - repo.MustFindAll(context.TODO(), &result, where.Like("title", "%dummies%")) - assert.NotEqual(t, books, result) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/find_and_count_all.go b/reltest/find_and_count_all.go deleted file mode 100644 index 5820fba4..00000000 --- a/reltest/find_and_count_all.go +++ /dev/null @@ -1,43 +0,0 @@ -package reltest - -import ( - "fmt" - "reflect" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// FindAndCountAll asserts and simulate find all function for test. -type FindAndCountAll struct { - *Expect -} - -// Result sets the result of this query. -func (fa *FindAndCountAll) Result(records interface{}, count int) { - fa.Arguments[1] = mock.AnythingOfType(fmt.Sprintf("*%T", records)) - - fa.Run(func(args mock.Arguments) { - reflect.ValueOf(args[1]).Elem().Set(reflect.ValueOf(records)) - }).Return(count, nil) -} - -// Error sets error to be returned. -func (fa *FindAndCountAll) Error(err error) { - fa.Return(0, err) -} - -// ConnectionClosed sets this error to be returned. -func (fa *FindAndCountAll) ConnectionClosed() { - fa.Error(ErrConnectionClosed) -} - -// ExpectFindAndCountAll to be called with given field and queries. -func ExpectFindAndCountAll(r *Repository, queriers []rel.Querier) *FindAndCountAll { - return &FindAndCountAll{ - Expect: newExpect(r, "FindAndCountAll", - []interface{}{r.ctxData, mock.Anything, queriers}, - []interface{}{0, nil}, - ), - } -} diff --git a/reltest/find_and_count_all_test.go b/reltest/find_and_count_all_test.go deleted file mode 100644 index 6ddb536c..00000000 --- a/reltest/find_and_count_all_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/go-rel/rel" - "github.com/go-rel/rel/where" - "github.com/stretchr/testify/assert" -) - -func TestFindAndCountAll(t *testing.T) { - var ( - repo = New() - result []Book - books = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - query = rel.Where(where.Like("title", "%dummies%")).Limit(10).Offset(10) - ) - - repo.ExpectFindAndCountAll(query).Result(books, 12) - - count, err := repo.FindAndCountAll(context.TODO(), &result, query) - assert.Nil(t, err) - assert.Equal(t, 12, count) - assert.Equal(t, books, result) - repo.AssertExpectations(t) - - repo.ExpectFindAndCountAll(query).Result(books, 12) - assert.NotPanics(t, func() { - count := repo.MustFindAndCountAll(context.TODO(), &result, query) - assert.Equal(t, books, result) - assert.Equal(t, 12, count) - }) - repo.AssertExpectations(t) -} - -func TestFindAndCountAll_error(t *testing.T) { - var ( - repo = New() - result []Book - books = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - query = rel.Where(where.Like("title", "%dummies%")).Limit(10).Offset(10) - ) - - repo.ExpectFindAndCountAll(query).ConnectionClosed() - - count, err := repo.FindAndCountAll(context.TODO(), &result, query) - assert.Equal(t, sql.ErrConnDone, err) - assert.Equal(t, 0, count) - assert.NotEqual(t, books, result) - repo.AssertExpectations(t) - - repo.ExpectFindAndCountAll(query).ConnectionClosed() - assert.Panics(t, func() { - repo.MustFindAndCountAll(context.TODO(), &result, query) - }) - - assert.NotEqual(t, books, result) - repo.AssertExpectations(t) -} diff --git a/reltest/find_test.go b/reltest/find_test.go deleted file mode 100644 index 3459a435..00000000 --- a/reltest/find_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package reltest - -import ( - "context" - "testing" - - "github.com/go-rel/rel" - "github.com/go-rel/rel/where" - "github.com/stretchr/testify/assert" -) - -func TestFind(t *testing.T) { - var ( - repo = New() - result Book - book = Book{ID: 2, Title: "Rel for dummies"} - ) - - repo.ExpectFind(where.Eq("id", 2)).Result(book) - assert.Nil(t, repo.Find(context.TODO(), &result, where.Eq("id", 2))) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectFind(where.Eq("id", 2)).Result(book) - assert.NotPanics(t, func() { - repo.MustFind(context.TODO(), &result, where.Eq("id", 2)) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestFind_noResult(t *testing.T) { - var ( - result Book - repo = New() - book = Book{ID: 2, Title: "Rel for dummies"} - ) - - repo.ExpectFind(where.Eq("id", 2)).NotFound() - - assert.Equal(t, rel.NotFoundError{}, repo.Find(context.TODO(), &result, where.Eq("id", 2))) - assert.NotEqual(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectFind(where.Eq("id", 2)).NotFound() - assert.Panics(t, func() { - repo.MustFind(context.TODO(), &result, where.Eq("id", 2)) - assert.NotEqual(t, book, result) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/iterate.go b/reltest/iterate.go deleted file mode 100644 index 94eaa8dc..00000000 --- a/reltest/iterate.go +++ /dev/null @@ -1,76 +0,0 @@ -package reltest - -import ( - "io" - "reflect" - - "github.com/go-rel/rel" -) - -type data interface { - Len() int - Get(index int) *rel.Document -} - -type iterator struct { - current int - data data - err error -} - -func (i iterator) Close() error { - return nil -} - -func (i *iterator) Next(record interface{}) error { - if i.err != nil { - return i.err - } - - if i.data == nil || i.current == i.data.Len() { - return io.EOF - } - - var ( - doc = i.data.Get(i.current) - ) - - reflect.ValueOf(record).Elem().Set(doc.ReflectValue()) - - i.current++ - return nil -} - -// Iterate asserts and simulate iterate function for test. -type Iterate iterator - -// Error sets error to be returned. -func (i *Iterate) Error(err error) { - i.err = err -} - -// ConnectionClosed sets this error to be returned. -func (i *Iterate) ConnectionClosed() { - i.Error(ErrConnectionClosed) -} - -// Result sets the result of this query. -func (i *Iterate) Result(records interface{}) { - rt := reflect.TypeOf(records) - if rt.Kind() == reflect.Ptr { - rt = rt.Elem() - } - - if rt.Kind() == reflect.Slice { - i.data = rel.NewCollection(records, true) - } else { - i.data = rel.NewDocument(records, true) - } -} - -// ExpectIterate to be called. -func ExpectIterate(r *Repository, query rel.Query, options []rel.IteratorOption) *Iterate { - iterate := &Iterate{} - r.mock.On("Iterate", r.ctxData, query, options).Return(iterate).Once() - return iterate -} diff --git a/reltest/iterate_test.go b/reltest/iterate_test.go deleted file mode 100644 index fe50d77d..00000000 --- a/reltest/iterate_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package reltest - -import ( - "context" - "io" - "testing" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/assert" -) - -func TestIterate(t *testing.T) { - tests := []struct { - name string - result interface{} - count int - }{ - { - name: "struct", - result: Book{ID: 1}, - count: 1, - }, - { - name: "struct pointer", - result: &Book{ID: 1}, - count: 1, - }, - { - name: "slice", - result: []Book{{ID: 1}, {ID: 2}}, - count: 2, - }, - { - name: "slice pointer", - result: &[]Book{{ID: 1}, {ID: 2}}, - count: 2, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - var ( - book Book - repo = New() - query = rel.From("users") - ) - - repo.ExpectIterate(query, rel.BatchSize(500)).Result(test.result) - - var ( - count = 0 - it = repo.Iterate(context.TODO(), query, rel.BatchSize(500)) - ) - - defer it.Close() - for { - if err := it.Next(&book); err == io.EOF { - break - } else { - assert.Nil(t, err) - } - - assert.NotEqual(t, 0, book.ID) - count++ - } - - assert.Equal(t, test.count, count) - repo.AssertExpectations(t) - }) - } -} - -func TestIterate_single(t *testing.T) { - var ( - book Book - repo = New() - query = rel.From("users") - ) - - repo.ExpectIterate(query).Result(Book{ID: 1}) - - count := 0 - it := repo.Iterate(context.TODO(), query) - defer it.Close() - for { - if err := it.Next(&book); err == io.EOF { - break - } else { - assert.Nil(t, err) - } - - assert.NotEqual(t, 0, book.ID) - count++ - } - - assert.Equal(t, 1, count) - repo.AssertExpectations(t) -} - -func TestIterate_error(t *testing.T) { - var ( - book Book - repo = New() - query = rel.From("users") - ) - - repo.ExpectIterate(query).ConnectionClosed() - - it := repo.Iterate(context.TODO(), query) - defer it.Close() - - assert.Equal(t, ErrConnectionClosed, it.Next(&book)) - repo.AssertExpectations(t) -} diff --git a/reltest/mutate.go b/reltest/mutate.go deleted file mode 100644 index 3c7289ba..00000000 --- a/reltest/mutate.go +++ /dev/null @@ -1,71 +0,0 @@ -package reltest - -import ( - "strings" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// Mutate asserts and simulate insert or update function for test. -type Mutate struct { - *Expect -} - -// For match expect calls for given record. -func (m *Mutate) For(record interface{}) *Mutate { - m.Arguments[1] = record - return m -} - -// ForType match expect calls for given type. -// Type must include package name, example: `model.User`. -func (m *Mutate) ForType(typ string) *Mutate { - return m.For(mock.AnythingOfType("*" + strings.TrimPrefix(typ, "*"))) -} - -// NotUnique sets not unique error to be returned. -func (m *Mutate) NotUnique(key string) { - m.Error(rel.ConstraintError{ - Key: key, - Type: rel.UniqueConstraint, - }) -} - -func expectMutate(r *Repository, methodName string, mutators []rel.Mutator) *Mutate { - mutatorsArgument := interface{}(mutators) - if mutators == nil { - mutatorsArgument = mock.Anything - } - - em := &Mutate{ - Expect: newExpect(r, methodName, - []interface{}{r.ctxData, mock.Anything, mutatorsArgument}, - []interface{}{nil}, - ), - } - - return em -} - -// ExpectInsert to be called with given field and queries. -func ExpectInsert(r *Repository, mutators []rel.Mutator) *Mutate { - return expectMutate(r, "Insert", mutators) -} - -// ExpectUpdate to be called with given field and queries. -func ExpectUpdate(r *Repository, mutators []rel.Mutator) *Mutate { - return expectMutate(r, "Update", mutators) -} - -// ExpectInsertAll to be called. -func ExpectInsertAll(r *Repository) *Mutate { - em := &Mutate{ - Expect: newExpect(r, "InsertAll", - []interface{}{r.ctxData, mock.Anything}, - []interface{}{nil}, - ), - } - - return em -} diff --git a/reltest/mutate_any.go b/reltest/mutate_any.go deleted file mode 100644 index adac70b6..00000000 --- a/reltest/mutate_any.go +++ /dev/null @@ -1,65 +0,0 @@ -package reltest - -import ( - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// MutateAny asserts and simulate mutate all function for test. -type MutateAny struct { - *Expect -} - -// Unsafe allows for unsafe operation that doesn't contains where clause. -func (ma *MutateAny) Unsafe() { - ma.RunFn = nil // clear validation -} - -// Result sets the returned number of deleted/updated counts. -func (ma *MutateAny) Result(count int) { - ma.Return(count, nil) -} - -// Error sets error to be returned. -func (ma *MutateAny) Error(err error) { - ma.Return(0, err) -} - -// ConnectionClosed sets this error to be returned. -func (ma *MutateAny) ConnectionClosed() { - ma.Error(ErrConnectionClosed) -} - -func expectMutateAny(r *Repository, methodName string, args ...interface{}) *MutateAny { - ma := &MutateAny{ - Expect: newExpect(r, methodName, - args, - []interface{}{0, nil}, - ), - } - - // validation - ma.Run(func(args mock.Arguments) { - query := args[1].(rel.Query) - - if query.Table == "" { - panic("reltest: cannot call " + methodName + " without specifying table name. use rel.From(tableName)") - } - - if query.WhereQuery.None() { - panic("reltest: unsafe " + methodName + " detected. if you want to mutate all records without filter, please use call .Unsafe()") - } - }) - - return ma -} - -// ExpectUpdateAny to be called. -func ExpectUpdateAny(r *Repository, query rel.Query, mutates []rel.Mutate) *MutateAny { - return expectMutateAny(r, "UpdateAny", r.ctxData, query, mutates) -} - -// ExpectDeleteAny to be called. -func ExpectDeleteAny(r *Repository, query rel.Query) *MutateAny { - return expectMutateAny(r, "DeleteAny", r.ctxData, query) -} diff --git a/reltest/mutate_any_test.go b/reltest/mutate_any_test.go deleted file mode 100644 index 13d6ccda..00000000 --- a/reltest/mutate_any_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/go-rel/rel" - "github.com/go-rel/rel/where" - "github.com/stretchr/testify/assert" -) - -func TestUpdateAny(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectUpdateAny(rel.From("books").Where(where.Eq("id", 1)), rel.Set("discount", true)).Result(1) - updatedCount, err := repo.UpdateAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1)), rel.Set("discount", true)) - assert.Nil(t, err) - assert.Equal(t, 1, updatedCount) - repo.AssertExpectations(t) - - repo.ExpectUpdateAny(rel.From("books").Where(where.Eq("id", 1)), rel.Set("discount", true)).Result(1) - assert.NotPanics(t, func() { - updatedCount = repo.MustUpdateAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1)), rel.Set("discount", true)) - assert.Equal(t, 1, updatedCount) - }) - repo.AssertExpectations(t) -} - -func TestDeleteAny(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDeleteAny(rel.From("books").Where(where.Eq("id", 1))).Result(1) - deletedCount, err := repo.DeleteAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1))) - assert.Nil(t, err) - assert.Equal(t, 1, deletedCount) - repo.AssertExpectations(t) - - repo.ExpectDeleteAny(rel.From("books").Where(where.Eq("id", 1))).Result(1) - assert.NotPanics(t, func() { - deletedCount = repo.MustDeleteAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1))) - assert.Equal(t, 1, deletedCount) - }) - repo.AssertExpectations(t) -} - -func TestDeleteAny_error(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDeleteAny(rel.From("books").Where(where.Eq("id", 1))).ConnectionClosed() - _, err := repo.DeleteAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1))) - assert.Equal(t, sql.ErrConnDone, err) - repo.AssertExpectations(t) - - repo.ExpectDeleteAny(rel.From("books").Where(where.Eq("id", 1))).ConnectionClosed() - assert.Panics(t, func() { - repo.MustDeleteAny(context.TODO(), rel.From("books").Where(where.Eq("id", 1))) - }) - repo.AssertExpectations(t) -} - -func TestDeleteAny_noTable(t *testing.T) { - var ( - repo = New() - query = rel.Where(where.Eq("id", 1)) - ) - - repo.ExpectDeleteAny(query) - assert.Panics(t, func() { - repo.MustDeleteAny(context.TODO(), query) - }) - repo.AssertExpectations(t) -} - -func TestDeleteAny_unsafe(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectDeleteAny(rel.From("books")) - assert.Panics(t, func() { - repo.MustDeleteAny(context.TODO(), rel.From("books")) - }) - repo.AssertExpectations(t) - - repo.ExpectDeleteAny(rel.From("books")).Unsafe() - assert.NotPanics(t, func() { - repo.MustDeleteAny(context.TODO(), rel.From("books")) - }) - repo.AssertExpectations(t) -} diff --git a/reltest/mutate_test.go b/reltest/mutate_test.go deleted file mode 100644 index e103407a..00000000 --- a/reltest/mutate_test.go +++ /dev/null @@ -1,599 +0,0 @@ -package reltest - -import ( - "context" - "errors" - "testing" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/assert" -) - -func TestMutate_Insert(t *testing.T) { - var ( - repo = New() - result = Book{Title: "Golang for dummies"} - book = Book{ID: 1, Title: "Golang for dummies"} - ) - - repo.ExpectInsert() - assert.Nil(t, repo.Insert(context.TODO(), &result)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectInsert() - assert.NotPanics(t, func() { - repo.MustInsert(context.TODO(), &result) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_nested(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ - Title: "Rel for dummies", - AuthorID: &authorID, - Author: Author{ID: 1, Name: "Kia"}, - Ratings: []Rating{ - {Score: 9}, - {Score: 10}, - }, - Poster: Poster{Image: "http://image.url"}, - } - book = Book{ - ID: 1, - Title: "Rel for dummies", - Author: Author{ID: 1, Name: "Kia"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 1, Score: 9, BookID: 1}, - {ID: 2, Score: 10, BookID: 1}, - }, - Poster: Poster{ID: 1, BookID: 1, Image: "http://image.url"}, - } - ) - - repo.ExpectInsert() - assert.Nil(t, repo.Insert(context.TODO(), &result)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectInsert() - assert.NotPanics(t, func() { - repo.MustInsert(context.TODO(), &result) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_record(t *testing.T) { - var ( - repo = New() - result = Book{Title: "Golang for dummies"} - book = Book{ID: 1, Title: "Golang for dummies"} - ) - - repo.ExpectInsert().ForType("reltest.Book") - assert.Nil(t, repo.Insert(context.TODO(), &result)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectInsert().ForType("reltest.Book") - assert.NotPanics(t, func() { - repo.MustInsert(context.TODO(), &result) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_set(t *testing.T) { - var ( - repo = New() - result Book - book = Book{ID: 1, Title: "Rel for dummies"} - ) - - repo.ExpectInsert(rel.Set("title", "Rel for dummies")) - assert.Nil(t, repo.Insert(context.TODO(), &result, rel.Set("title", "Rel for dummies"))) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectInsert(rel.Set("title", "Rel for dummies")) - assert.NotPanics(t, func() { - repo.MustInsert(context.TODO(), &result, rel.Set("title", "Rel for dummies")) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_map(t *testing.T) { - var ( - repo = New() - result Book - book = Book{ - ID: 1, - Title: "Rel for dummies", - Ratings: []Rating{ - {ID: 1, Score: 9, BookID: 1}, - {ID: 2, Score: 10, BookID: 1}, - }, - Poster: Poster{ID: 1, BookID: 1, Image: "http://image.url"}, - } - mut = rel.Map{ - "title": "Rel for dummies", - "ratings": []rel.Map{ - {"score": 9}, - {"score": 10}, - }, - "poster": rel.Map{ - "image": "http://image.url", - }, - } - ) - - repo.ExpectInsert(mut) - assert.Nil(t, repo.Insert(context.TODO(), &result, mut)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectInsert(mut) - assert.NotPanics(t, func() { - repo.MustInsert(context.TODO(), &result, mut) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_unknownField(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectInsert(rel.Set("titles", "Rel for dummies")) - assert.Panics(t, func() { - _ = repo.Insert(context.TODO(), &result, rel.Set("titles", "Rel for dummies")) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Insert_notUnique(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectInsert(rel.Set("title", "Rel for dummies")).NotUnique("title") - assert.Equal(t, - rel.ConstraintError{Key: "title", Type: rel.UniqueConstraint}, - repo.Insert(context.TODO(), &result, rel.Set("title", "Rel for dummies")), - ) - repo.AssertExpectations(t) -} - -func TestMutate_InsertAll(t *testing.T) { - var ( - repo = New() - results = []Book{ - {Title: "Golang for dummies"}, - {Title: "Rel for dummies"}, - } - books = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - ) - - repo.ExpectInsertAll() - assert.Nil(t, repo.InsertAll(context.TODO(), &results)) - assert.Equal(t, books, results) - repo.AssertExpectations(t) - - repo.ExpectInsertAll() - assert.NotPanics(t, func() { - repo.MustInsertAll(context.TODO(), &results) - assert.Equal(t, books, results) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectUpdate() - assert.Nil(t, repo.Update(context.TODO(), &result)) - repo.AssertExpectations(t) - - repo.ExpectUpdate() - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_nested(t *testing.T) { - var ( - repo = New() - authorID = 2 - result = Book{ - ID: 2, - Title: "Rel for dummies", - Author: Author{ID: 2, Name: "Kia"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 1, BookID: 2, Score: 9}, - {ID: 2, BookID: 2, Score: 10}, - }, - Poster: Poster{ID: 1, BookID: 2, Image: "http://image.url"}, - } - book = Book{ - ID: 2, - Title: "Rel for dummies", - Author: Author{ID: 2, Name: "Kia"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 1, BookID: 2, Score: 9}, - {ID: 2, BookID: 2, Score: 10}, - }, - Poster: Poster{ID: 1, BookID: 2, Image: "http://image.url"}, - } - ) - - repo.ExpectUpdate() - assert.Nil(t, repo.Update(context.TODO(), &result)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectUpdate() - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_nestedInsert(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ - ID: 2, - Title: "Rel for dummies", - AuthorID: &authorID, - Author: Author{ID: authorID, Name: "Kia"}, - Ratings: []Rating{ - {Score: 9}, - {Score: 10}, - }, - Poster: Poster{Image: "http://image.url"}, - } - book = Book{ - ID: 2, - Title: "Rel for dummies", - Author: Author{ID: 1, Name: "Kia"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 1, BookID: 2, Score: 9}, - {ID: 2, BookID: 2, Score: 10}, - }, - Poster: Poster{ID: 1, BookID: 2, Image: "http://image.url"}, - } - ) - - repo.ExpectUpdate() - assert.Nil(t, repo.Update(context.TODO(), &result)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectUpdate() - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_record(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectUpdate().For(&result) - assert.Nil(t, repo.Update(context.TODO(), &result)) - repo.AssertExpectations(t) - - repo.ExpectUpdate().For(&result) - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result) - }) - repo.AssertExpectations(t) -} - -// func TestMutate_Update_withoutPrimaryValue(t *testing.T) { -// var ( -// repo = New() -// result = Book{Title: "Golang for dummies"} -// ) - -// repo.ExpectUpdate().For(&result) -// assert.Panics(t, func() { -// _ = repo.Update(context.TODO(),&result) -// }) -// repo.AssertExpectations(t) -// } - -func TestMutate_Update_set(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - book = Book{ID: 2, Title: "Rel for dummies"} - ) - - repo.ExpectUpdate(rel.Set("title", "Rel for dummies")) - assert.Nil(t, repo.Update(context.TODO(), &result, rel.Set("title", "Rel for dummies"))) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectUpdate(rel.Set("title", "Rel for dummies")) - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result, rel.Set("title", "Rel for dummies")) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -// func TestMutate_Update_inc(t *testing.T) { -// var ( -// repo = New() -// result = Book{ID: 2, Views: 10} -// book = Book{ID: 2, Views: 11} -// ) - -// repo.ExpectUpdate(rel.Inc("views")) -// assert.Nil(t, repo.Update(context.TODO(),&result, rel.Inc("views"))) -// assert.Equal(t, book, result) -// repo.AssertExpectations(t) -// } - -// func TestMutate_Update_dec(t *testing.T) { -// var ( -// repo = New() -// result = Book{ID: 2, Views: 10} -// book = Book{ID: 2, Views: 9} -// ) - -// repo.ExpectUpdate(rel.Dec("views")) -// assert.Nil(t, repo.Update(context.TODO(),&result, rel.Dec("views"))) -// assert.Equal(t, book, result) -// repo.AssertExpectations(t) -// } - -func TestMutate_Update_incOrDecFieldNotExists(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Views: 10} - ) - - repo.ExpectUpdate(rel.Inc("watistis")) - assert.Panics(t, func() { - assert.Nil(t, repo.Update(context.TODO(), &result, rel.Inc("watistis"))) - }) - - repo.AssertExpectations(t) -} - -func TestMutate_Update_incOrDecFieldInvalid(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Views: 10} - ) - - repo.ExpectUpdate(rel.Inc("title")) - assert.Panics(t, func() { - assert.Nil(t, repo.Update(context.TODO(), &result, rel.Inc("title"))) - }) - - repo.AssertExpectations(t) -} - -func TestMutate_Update_setNil(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - book = Book{ID: 2, Title: ""} - ) - - repo.ExpectUpdate(rel.Set("title", nil)) - assert.Nil(t, repo.Update(context.TODO(), &result, rel.Set("title", nil))) - assert.Equal(t, book, result) - repo.AssertExpectations(t) -} - -func TestMutate_Update_map(t *testing.T) { - var ( - repo = New() - authorID = 2 - result = Book{ - ID: 2, - Title: "Golang for dummies", - Author: Author{ID: 2, Name: "unknown"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 4, BookID: 2, Score: 15}, - {ID: 2, BookID: 2, Score: 5}, - {ID: 3, BookID: 2, Score: 6}, - }, - } - book = Book{ - ID: 2, - Title: "Rel for dummies", - Author: Author{ID: 2, Name: "Kia"}, - AuthorID: &authorID, - Ratings: []Rating{ - {ID: 2, BookID: 2, Score: 9}, - {ID: 1, BookID: 2, Score: 10}, - }, - Poster: Poster{ID: 1, BookID: 2, Image: "http://image.url"}, - } - mut = rel.Map{ - "title": "Rel for dummies", - "author": rel.Map{ - "id": 2, - "name": "Kia", - }, - "ratings": []rel.Map{ - {"id": 2, "score": 9}, - {"score": 10}, - }, - "poster": rel.Map{ - "image": "http://image.url", - }, - } - ) - - repo.ExpectUpdate(mut) - assert.Nil(t, repo.Update(context.TODO(), &result, mut)) - assert.Equal(t, book, result) - repo.AssertExpectations(t) - - repo.ExpectUpdate(mut) - assert.NotPanics(t, func() { - repo.MustUpdate(context.TODO(), &result, mut) - assert.Equal(t, book, result) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_belongsToInconsistentFk(t *testing.T) { - var ( - repo = New() - result = Book{ - ID: 2, - Title: "Golang for dummies", - AbstractID: 3, - Abstract: Abstract{ID: 2, Content: "REL for Dummies"}, - } - mut = rel.Map{ - "abstract": rel.Map{ - "id": 2, - "content": "lorem ipsum", - }, - } - ) - - repo.ExpectUpdate(mut) - assert.Equal(t, rel.ConstraintError{ - Key: "abstract_id", - Type: rel.ForeignKeyConstraint, - Err: errors.New("rel: inconsistent belongs to ref and fk"), - }, repo.Update(context.TODO(), &result, mut)) - repo.AssertExpectations(t) -} - -func TestMutate_Update_hasOneInconsistentPk(t *testing.T) { - var ( - repo = New() - result = Book{ - ID: 2, - Title: "Golang for dummies", - Poster: Poster{ID: 1, BookID: 2, Image: "http://image.url"}, - } - mut = rel.Map{ - "poster": rel.Map{ - "id": 2, - "image": "http://image.url/other", - }, - } - ) - - repo.ExpectUpdate(mut) - assert.Panics(t, func() { - _ = repo.Update(context.TODO(), &result, mut) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_hasOneInconsistentFk(t *testing.T) { - var ( - repo = New() - result = Book{ - ID: 2, - Title: "Golang for dummies", - Poster: Poster{ID: 1, BookID: 1, Image: "http://image.url"}, - } - mut = rel.Map{ - "poster": rel.Map{ - "id": 1, - "image": "http://image.url/other", - }, - } - ) - - repo.ExpectUpdate(mut) - assert.Equal(t, rel.ConstraintError{ - Key: "book_id", - Type: rel.ForeignKeyConstraint, - Err: errors.New("rel: inconsistent has one ref and fk"), - }, repo.Update(context.TODO(), &result, mut)) - repo.AssertExpectations(t) -} - -func TestMutate_Update_hasManyInconsistentFk(t *testing.T) { - var ( - repo = New() - result = Book{ - ID: 2, - Title: "Golang for dummies", - Ratings: []Rating{ - {ID: 2, BookID: 1, Score: 5}, - }, - } - mut = rel.Map{ - "ratings": []rel.Map{ - {"id": 2, "score": 9}, - }, - } - ) - - repo.ExpectUpdate(mut) - assert.Equal(t, rel.ConstraintError{ - Key: "book_id", - Type: rel.ForeignKeyConstraint, - Err: errors.New("rel: inconsistent has many ref and fk"), - }, repo.Update(context.TODO(), &result, mut)) - repo.AssertExpectations(t) -} - -func TestMutate_Update_unknownField(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectUpdate(rel.Set("titles", "Rel for dummies")) - assert.Panics(t, func() { - _ = repo.Update(context.TODO(), &result, rel.Set("titles", "Rel for dummies")) - }) - repo.AssertExpectations(t) -} - -func TestMutate_Update_notUnique(t *testing.T) { - var ( - repo = New() - result = Book{ID: 2, Title: "Golang for dummies"} - ) - - repo.ExpectUpdate(rel.Set("title", "Rel for dummies")).NotUnique("title") - assert.Equal(t, - rel.ConstraintError{Key: "title", Type: rel.UniqueConstraint}, - repo.Update(context.TODO(), &result, rel.Set("title", "Rel for dummies")), - ) - repo.AssertExpectations(t) -} diff --git a/reltest/nop_adapter.go b/reltest/nop_adapter.go deleted file mode 100644 index 63ba0893..00000000 --- a/reltest/nop_adapter.go +++ /dev/null @@ -1,99 +0,0 @@ -package reltest - -import ( - "context" - - "github.com/go-rel/rel" -) - -type nopAdapter struct { -} - -func (na *nopAdapter) Close() error { - return nil -} - -func (na *nopAdapter) Instrumentation(instrumenter rel.Instrumenter) { -} - -func (na *nopAdapter) Ping(ctx context.Context) error { - return nil -} - -func (na *nopAdapter) Aggregate(ctx context.Context, query rel.Query, mode string, field string) (int, error) { - return 0, nil -} - -func (na *nopAdapter) Begin(ctx context.Context) (rel.Adapter, error) { - return na, nil -} - -func (na *nopAdapter) Commit(ctx context.Context) error { - return nil -} - -func (na *nopAdapter) Delete(ctx context.Context, query rel.Query) (int, error) { - return 1, nil -} - -func (na *nopAdapter) Insert(ctx context.Context, query rel.Query, primaryField string, mutates map[string]rel.Mutate) (interface{}, error) { - return 1, nil -} - -func (na *nopAdapter) InsertAll(ctx context.Context, query rel.Query, primaryField string, fields []string, bulkMutates []map[string]rel.Mutate) ([]interface{}, error) { - var ( - ids = make([]interface{}, len(bulkMutates)) - ) - - for i := range bulkMutates { - ids[i] = i + 1 - } - - return ids, nil -} - -func (na *nopAdapter) Query(ctx context.Context, query rel.Query) (rel.Cursor, error) { - return &nopCursor{count: 1}, nil -} - -func (na *nopAdapter) Rollback(ctx context.Context) error { - return nil -} - -func (na *nopAdapter) Update(ctx context.Context, query rel.Query, primaryField string, mutates map[string]rel.Mutate) (int, error) { - return 1, nil -} - -func (na *nopAdapter) Apply(ctx context.Context, migration rel.Migration) error { - return nil -} - -func (na *nopAdapter) Exec(ctx context.Context, stmt string, args []interface{}) (int64, int64, error) { - return 0, 0, nil -} - -type nopCursor struct { - count int -} - -func (nc *nopCursor) Close() error { - return nil -} - -func (nc *nopCursor) Fields() ([]string, error) { - return nil, nil -} - -func (nc *nopCursor) Next() bool { - nc.count-- - return nc.count >= 0 -} - -func (nc *nopCursor) Scan(...interface{}) error { - nc.NopScanner() - return nil -} - -func (nc *nopCursor) NopScanner() interface{} { - return nil -} diff --git a/reltest/nop_adapter_test.go b/reltest/nop_adapter_test.go deleted file mode 100644 index 645a28f1..00000000 --- a/reltest/nop_adapter_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package reltest - -import ( - "context" - "testing" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/assert" -) - -func TestNopAdapter_Apply(t *testing.T) { - var ( - ctx = context.TODO() - adapter = &nopAdapter{} - ) - - assert.Nil(t, adapter.Apply(ctx, rel.Table{})) -} - -func TestNopAdapter_Exec(t *testing.T) { - var ( - ctx = context.TODO() - adapter = &nopAdapter{} - ) - - rowsAffected, lastInsertedID, err := adapter.Exec(ctx, "", nil) - assert.Zero(t, rowsAffected) - assert.Zero(t, lastInsertedID) - assert.Nil(t, err) -} - -func TestNopAdapter_Clos3(t *testing.T) { - var ( - adapter = &nopAdapter{} - ) - - assert.Nil(t, adapter.Close()) -} diff --git a/reltest/preload.go b/reltest/preload.go deleted file mode 100644 index 23a7fb5b..00000000 --- a/reltest/preload.go +++ /dev/null @@ -1,182 +0,0 @@ -package reltest - -import ( - "reflect" - "strings" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// Preload asserts and simulate preload function for test. -type Preload struct { - *Expect -} - -// Result sets the result of Preload query. -func (p *Preload) Result(records interface{}) { - p.Run(func(args mock.Arguments) { - var ( - target = asSlice(args[1], false) - result = asSlice(records, true) - path = strings.Split(args[2].(string), ".") - ) - - preload(target, result, path) - }) -} - -// For match expect calls for given record. -func (p *Preload) For(record interface{}) *Preload { - p.Arguments[1] = record - return p -} - -// ForType match expect calls for given type. -// Type must include package name, example: `model.User`. -func (p *Preload) ForType(typ string) *Preload { - return p.For(mock.AnythingOfType("*" + strings.TrimPrefix(typ, "*"))) -} - -// ExpectPreload to be called with given field and queries. -func ExpectPreload(r *Repository, field string, queriers []rel.Querier) *Preload { - return &Preload{ - Expect: newExpect(r, "Preload", - []interface{}{r.ctxData, mock.Anything, field, queriers}, - []interface{}{nil}, - ), - } -} - -type slice interface { - ReflectValue() reflect.Value - Reset() - Get(index int) *rel.Document - Len() int -} - -func asSlice(v interface{}, readonly bool) slice { - var ( - sl slice - rt = reflect.TypeOf(v) - ) - - if rt.Kind() == reflect.Ptr { - rt = rt.Elem() - } - - if rt.Kind() == reflect.Slice { - sl = rel.NewCollection(v, readonly) - } else { - sl = rel.NewDocument(v, readonly) - } - - return sl -} - -func preload(target slice, result slice, path []string) { - type frame struct { - index int - doc *rel.Document - } - - var ( - mappedResult map[interface{}]reflect.Value - stack = make([]frame, target.Len()) - ) - - // init stack - for i := 0; i < len(stack); i++ { - stack[i] = frame{index: 0, doc: target.Get(i)} - } - - for len(stack) > 0 { - var ( - n = len(stack) - 1 - top = stack[n] - assocs = top.doc.Association(path[top.index]) - hasMany = assocs.Type() == rel.HasMany - ) - - stack = stack[:n] - - if top.index == len(path)-1 { - var ( - curr slice - rValue = assocs.ReferenceValue() - fField = assocs.ForeignField() - ) - - if rValue == nil { - continue - } - - if hasMany { - curr, _ = assocs.Collection() - } else { - curr, _ = assocs.Document() - } - - curr.Reset() - - if mappedResult == nil { - mappedResult = mapResult(result, fField, hasMany) - } - - if rv, ok := mappedResult[rValue]; ok { - curr.ReflectValue().Set(rv) - } - } else { - if assocs.Type() == rel.HasMany { - var ( - col, loaded = assocs.Collection() - ) - - if !loaded { - continue - } - - stack = append(stack, make([]frame, col.Len())...) - for i := 0; i < col.Len(); i++ { - stack[n+i] = frame{ - index: top.index + 1, - doc: col.Get(i), - } - } - } else { - if doc, loaded := assocs.Document(); loaded { - stack = append(stack, frame{ - index: top.index + 1, - doc: doc, - }) - } - } - } - } -} - -func mapResult(result slice, fField string, hasMany bool) map[interface{}]reflect.Value { - var ( - mapResult = make(map[interface{}]reflect.Value) - ) - - for i := 0; i < result.Len(); i++ { - var ( - doc = result.Get(i) - rv = doc.ReflectValue() - fValue, _ = doc.Value(fField) - ) - - if hasMany { - if _, ok := mapResult[fValue]; !ok { - mapResult[fValue] = reflect.MakeSlice(reflect.SliceOf(rv.Type()), 0, 0) - } - - mapResult[fValue] = reflect.Append(mapResult[fValue], rv) - } else { - mapResult[fValue] = rv - } - } - - return mapResult -} diff --git a/reltest/preload_test.go b/reltest/preload_test.go deleted file mode 100644 index 9f6d5540..00000000 --- a/reltest/preload_test.go +++ /dev/null @@ -1,205 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPreload(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ID: 2, Title: "Rel for dummies", AuthorID: &authorID} - author = Author{ID: 1, Name: "Kia"} - ) - - repo.ExpectPreload("author").Result(author) - assert.Nil(t, repo.Preload(context.TODO(), &result, "author")) - assert.Equal(t, author, result.Author) - repo.AssertExpectations(t) - - repo.ExpectPreload("author").Result(author) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "author") - }) - assert.Equal(t, author, result.Author) - repo.AssertExpectations(t) -} - -func TestPreload_nested(t *testing.T) { - var ( - repo = New() - author = Author{ID: 1, Name: "Kia"} - result = Rating{ - Book: &Book{ID: 2, Title: "Rel for dummies", AuthorID: &author.ID}, - } - ) - - repo.ExpectPreload("book.author").Result(author) - assert.Nil(t, repo.Preload(context.TODO(), &result, "book.author")) - assert.Equal(t, author, result.Book.Author) - repo.AssertExpectations(t) - - repo.ExpectPreload("book.author").Result(author) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "book.author") - }) - assert.Equal(t, author, result.Book.Author) - repo.AssertExpectations(t) -} - -func TestPreload_slice(t *testing.T) { - var ( - repo = New() - result = []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - } - ratings = []Rating{ - {ID: 1, BookID: 1, Score: 10}, - {ID: 2, BookID: 1, Score: 8}, - {ID: 3, BookID: 2, Score: 9}, - } - ) - - repo.ExpectPreload("ratings").Result(ratings) - assert.Nil(t, repo.Preload(context.TODO(), &result, "ratings")) - assert.Len(t, result[0].Ratings, 2) - assert.Equal(t, ratings[:2], result[0].Ratings) - assert.Len(t, result[1].Ratings, 1) - assert.Equal(t, ratings[2:], result[1].Ratings) - repo.AssertExpectations(t) - - repo.ExpectPreload("ratings").Result(ratings) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "ratings") - }) - assert.Len(t, result[0].Ratings, 2) - assert.Equal(t, ratings[:2], result[0].Ratings) - assert.Len(t, result[1].Ratings, 1) - assert.Equal(t, ratings[2:], result[1].Ratings) - repo.AssertExpectations(t) -} - -func TestPreload_sliceNested(t *testing.T) { - var ( - repo = New() - result = []Author{ - { - Books: []Book{ - {ID: 1, Title: "Golang for dummies"}, - {ID: 2, Title: "Rel for dummies"}, - }, - }, - { - Books: nil, - }, - } - ratings = []Rating{ - {ID: 1, BookID: 1, Score: 10}, - {ID: 2, BookID: 1, Score: 8}, - {ID: 3, BookID: 2, Score: 9}, - } - ) - - repo.ExpectPreload("books.ratings").Result(ratings) - assert.Nil(t, repo.Preload(context.TODO(), &result, "books.ratings")) - assert.Len(t, result[0].Books[0].Ratings, 2) - assert.Equal(t, ratings[:2], result[0].Books[0].Ratings) - assert.Len(t, result[0].Books[1].Ratings, 1) - assert.Equal(t, ratings[2:], result[0].Books[1].Ratings) - repo.AssertExpectations(t) - - repo.ExpectPreload("books.ratings").Result(ratings) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "books.ratings") - }) - assert.Len(t, result[0].Books[0].Ratings, 2) - assert.Equal(t, ratings[:2], result[0].Books[0].Ratings) - assert.Len(t, result[0].Books[1].Ratings, 1) - assert.Equal(t, ratings[2:], result[0].Books[1].Ratings) - repo.AssertExpectations(t) -} - -func TestPreload_nilReferenceValue(t *testing.T) { - var ( - repo = New() - result = struct { - ID int - Author *Author - AuthorID *int - }{ - ID: 1, - } - author = Author{ID: 1, Name: "Kia"} - ) - - repo.ExpectPreload("author").Result(author) - assert.Nil(t, repo.Preload(context.TODO(), &result, "author")) - assert.Nil(t, result.Author) - repo.AssertExpectations(t) - - repo.ExpectPreload("author").Result(author) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "author") - }) - assert.Nil(t, result.Author) - repo.AssertExpectations(t) -} - -func TestPreload_For(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ID: 2, Title: "Rel for dummies", AuthorID: &authorID} - ) - - repo.ExpectPreload("author").For(&result) - assert.Nil(t, repo.Preload(context.TODO(), &result, "author")) - repo.AssertExpectations(t) - - repo.ExpectPreload("author").For(&result) - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "author") - }) - repo.AssertExpectations(t) -} - -func TestPreload_ForType(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ID: 2, Title: "Rel for dummies", AuthorID: &authorID} - ) - - repo.ExpectPreload("author").ForType("reltest.Book") - assert.Nil(t, repo.Preload(context.TODO(), &result, "author")) - repo.AssertExpectations(t) - - repo.ExpectPreload("author").ForType("reltest.Book") - assert.NotPanics(t, func() { - repo.MustPreload(context.TODO(), &result, "author") - }) - repo.AssertExpectations(t) -} - -func TestPreload_error(t *testing.T) { - var ( - repo = New() - authorID = 1 - result = Book{ID: 2, Title: "Rel for dummies", AuthorID: &authorID} - ) - - repo.ExpectPreload("author").ConnectionClosed() - assert.Equal(t, sql.ErrConnDone, repo.Preload(context.TODO(), &result, "author")) - repo.AssertExpectations(t) - - repo.ExpectPreload("author").ConnectionClosed() - assert.Panics(t, func() { - repo.MustPreload(context.TODO(), &result, "author") - }) - repo.AssertExpectations(t) -} diff --git a/reltest/reltest.go b/reltest/reltest.go deleted file mode 100644 index 31d327ee..00000000 --- a/reltest/reltest.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package reltest for unit testing database interaction. -// -// Deprecated: Use github.com/go-rel/reltest instead. -package reltest diff --git a/reltest/repository.go b/reltest/repository.go deleted file mode 100644 index 374ac922..00000000 --- a/reltest/repository.go +++ /dev/null @@ -1,351 +0,0 @@ -package reltest - -import ( - "context" - "runtime" - "testing" - - "github.com/go-rel/rel" - "github.com/stretchr/testify/mock" -) - -// Repository is an autogenerated mock type for the Repository type -type Repository struct { - repo rel.Repository - mock mock.Mock - ctxData ctxData -} - -var _ rel.Repository = (*Repository)(nil) - -// Adapter provides a mock function with given fields: -func (r *Repository) Adapter(ctx context.Context) rel.Adapter { - return r.repo.Adapter(ctx) -} - -// Instrumentation provides a mock function with given fields: instrumenter -func (r *Repository) Instrumentation(instrumenter rel.Instrumenter) { - r.repo.Instrumentation(instrumenter) -} - -// Ping database. -func (r *Repository) Ping(ctx context.Context) error { - return r.repo.Ping(ctx) -} - -// Iterate through a collection of records from database in batches. -// This function returns iterator that can be used to loop all records. -// Limit, Offset and Sort query is automatically ignored. -func (r *Repository) Iterate(ctx context.Context, query rel.Query, options ...rel.IteratorOption) rel.Iterator { - ret := r.mock.Called(fetchContext(ctx), query, options).Get(0) - return (*iterator)(ret.(*Iterate)) -} - -// ExpectIterate apply mocks and expectations for Iterate -func (r *Repository) ExpectIterate(query rel.Query, options ...rel.IteratorOption) *Iterate { - return ExpectIterate(r, query, options) -} - -// Aggregate provides a mock function with given fields: query, aggregate, field -func (r *Repository) Aggregate(ctx context.Context, query rel.Query, aggregate string, field string) (int, error) { - r.repo.Aggregate(ctx, query, aggregate, field) - ret := r.mock.Called(fetchContext(ctx), query, aggregate, field) - return ret.Int(0), ret.Error(1) -} - -// MustAggregate provides a mock function with given fields: query, aggregate, field -func (r *Repository) MustAggregate(ctx context.Context, query rel.Query, aggregate string, field string) int { - result, err := r.Aggregate(ctx, query, aggregate, field) - must(err) - return result -} - -// ExpectAggregate apply mocks and expectations for Aggregate -func (r *Repository) ExpectAggregate(query rel.Query, aggregate string, field string) *Aggregate { - return ExpectAggregate(r, query, aggregate, field) -} - -// Count provides a mock function with given fields: collection, queriers -func (r *Repository) Count(ctx context.Context, collection string, queriers ...rel.Querier) (int, error) { - r.repo.Count(ctx, collection, queriers...) - ret := r.mock.Called(fetchContext(ctx), collection, queriers) - return ret.Int(0), ret.Error(1) -} - -// MustCount provides a mock function with given fields: collection, queriers -func (r *Repository) MustCount(ctx context.Context, collection string, queriers ...rel.Querier) int { - count, err := r.Count(ctx, collection, queriers...) - must(err) - return count -} - -// ExpectCount apply mocks and expectations for Count -func (r *Repository) ExpectCount(collection string, queriers ...rel.Querier) *Aggregate { - return ExpectCount(r, collection, queriers) -} - -// Find provides a mock function with given fields: record, queriers -func (r *Repository) Find(ctx context.Context, record interface{}, queriers ...rel.Querier) error { - r.repo.Find(ctx, record, queriers...) - return r.mock.Called(fetchContext(ctx), record, queriers).Error(0) -} - -// MustFind provides a mock function with given fields: record, queriers -func (r *Repository) MustFind(ctx context.Context, record interface{}, queriers ...rel.Querier) { - must(r.Find(ctx, record, queriers...)) -} - -// ExpectFind apply mocks and expectations for Find -func (r *Repository) ExpectFind(queriers ...rel.Querier) *Find { - return ExpectFind(r, queriers) -} - -// FindAll provides a mock function with given fields: records, queriers -func (r *Repository) FindAll(ctx context.Context, records interface{}, queriers ...rel.Querier) error { - r.repo.FindAll(ctx, records, queriers...) - return r.mock.Called(fetchContext(ctx), records, queriers).Error(0) -} - -// MustFindAll provides a mock function with given fields: records, queriers -func (r *Repository) MustFindAll(ctx context.Context, records interface{}, queriers ...rel.Querier) { - must(r.FindAll(ctx, records, queriers...)) -} - -// ExpectFindAll apply mocks and expectations for FindAll -func (r *Repository) ExpectFindAll(queriers ...rel.Querier) *FindAll { - return ExpectFindAll(r, queriers) -} - -// FindAndCountAll provides a mock function with given fields: records, queriers -func (r *Repository) FindAndCountAll(ctx context.Context, records interface{}, queriers ...rel.Querier) (int, error) { - r.repo.FindAndCountAll(ctx, records, queriers...) - ret := r.mock.Called(fetchContext(ctx), records, queriers) - return ret.Int(0), ret.Error(1) -} - -// MustFindAndCountAll provides a mock function with given fields: records, queriers -func (r *Repository) MustFindAndCountAll(ctx context.Context, records interface{}, queriers ...rel.Querier) int { - count, err := r.FindAndCountAll(ctx, records, queriers...) - must(err) - return count -} - -// ExpectFindAndCountAll apply mocks and expectations for FindAndCountAll -func (r *Repository) ExpectFindAndCountAll(queriers ...rel.Querier) *FindAndCountAll { - return ExpectFindAndCountAll(r, queriers) -} - -// Insert provides a mock function with given fields: record, mutators -func (r *Repository) Insert(ctx context.Context, record interface{}, mutators ...rel.Mutator) error { - ret := r.mock.Called(fetchContext(ctx), record, mutators) - - r.repo.Insert(ctx, record, mutators...) - return ret.Error(0) -} - -// MustInsert provides a mock function with given fields: record, mutators -func (r *Repository) MustInsert(ctx context.Context, record interface{}, mutators ...rel.Mutator) { - must(r.Insert(ctx, record, mutators...)) -} - -// ExpectInsert apply mocks and expectations for Insert -func (r *Repository) ExpectInsert(mutators ...rel.Mutator) *Mutate { - return ExpectInsert(r, mutators) -} - -// InsertAll records. -func (r *Repository) InsertAll(ctx context.Context, records interface{}) error { - ret := r.mock.Called(fetchContext(ctx), records) - - r.repo.InsertAll(ctx, records) - return ret.Error(0) -} - -// MustInsertAll records. -func (r *Repository) MustInsertAll(ctx context.Context, records interface{}) { - must(r.InsertAll(ctx, records)) -} - -// ExpectInsertAll records. -func (r *Repository) ExpectInsertAll() *Mutate { - return ExpectInsertAll(r) -} - -// Update provides a mock function with given fields: record, mutators -func (r *Repository) Update(ctx context.Context, record interface{}, mutators ...rel.Mutator) error { - ret := r.mock.Called(fetchContext(ctx), record, mutators) - - if err := r.repo.Update(ctx, record, mutators...); err != nil { - return err - } - - return ret.Error(0) -} - -// MustUpdate provides a mock function with given fields: record, mutators -func (r *Repository) MustUpdate(ctx context.Context, record interface{}, mutators ...rel.Mutator) { - must(r.Update(ctx, record, mutators...)) -} - -// ExpectUpdate apply mocks and expectations for Update -func (r *Repository) ExpectUpdate(mutators ...rel.Mutator) *Mutate { - return ExpectUpdate(r, mutators) -} - -// UpdateAny provides a mock function with given fields: query -func (r *Repository) UpdateAny(ctx context.Context, query rel.Query, mutates ...rel.Mutate) (int, error) { - ret := r.mock.Called(fetchContext(ctx), query, mutates) - return ret.Int(0), ret.Error(1) -} - -// MustUpdateAny provides a mock function with given fields: query -func (r *Repository) MustUpdateAny(ctx context.Context, query rel.Query, mutates ...rel.Mutate) int { - updatedCount, err := r.UpdateAny(ctx, query, mutates...) - must(err) - return updatedCount -} - -// ExpectUpdateAny apply mocks and expectations for UpdateAny -func (r *Repository) ExpectUpdateAny(query rel.Query, mutates ...rel.Mutate) *MutateAny { - return ExpectUpdateAny(r, query, mutates) -} - -// Delete provides a mock function with given fields: record -func (r *Repository) Delete(ctx context.Context, record interface{}, options ...rel.Cascade) error { - return r.mock.Called(fetchContext(ctx), record, options).Error(0) -} - -// MustDelete provides a mock function with given fields: record -func (r *Repository) MustDelete(ctx context.Context, record interface{}, options ...rel.Cascade) { - must(r.Delete(ctx, record, options...)) -} - -// ExpectDelete apply mocks and expectations for Delete -func (r *Repository) ExpectDelete(options ...rel.Cascade) *Delete { - return ExpectDelete(r, options) -} - -// DeleteAll provides DeleteAll mock function with given fields: records -func (r *Repository) DeleteAll(ctx context.Context, records interface{}) error { - return r.mock.Called(fetchContext(ctx), records).Error(0) -} - -// MustDeleteAll provides a mock function with given fields: record -func (r *Repository) MustDeleteAll(ctx context.Context, record interface{}) { - must(r.DeleteAll(ctx, record)) -} - -// ExpectDeleteAll apply mocks and expectations for DeleteAll -func (r *Repository) ExpectDeleteAll() *Delete { - return ExpectDeleteAll(r) -} - -// DeleteAny provides a mock function with given fields: query -func (r *Repository) DeleteAny(ctx context.Context, query rel.Query) (int, error) { - ret := r.mock.Called(fetchContext(ctx), query) - return ret.Int(0), ret.Error(1) -} - -// MustDeleteAny provides a mock function with given fields: query -func (r *Repository) MustDeleteAny(ctx context.Context, query rel.Query) int { - deletedCount, err := r.DeleteAny(ctx, query) - must(err) - return deletedCount -} - -// ExpectDeleteAny apply mocks and expectations for DeleteAny -func (r *Repository) ExpectDeleteAny(query rel.Query) *MutateAny { - return ExpectDeleteAny(r, query) -} - -// Preload provides a mock function with given fields: records, field, queriers -func (r *Repository) Preload(ctx context.Context, records interface{}, field string, queriers ...rel.Querier) error { - return r.mock.Called(fetchContext(ctx), records, field, queriers).Error(0) -} - -// MustPreload provides a mock function with given fields: records, field, queriers -func (r *Repository) MustPreload(ctx context.Context, records interface{}, field string, queriers ...rel.Querier) { - must(r.Preload(ctx, records, field, queriers...)) -} - -// ExpectPreload apply mocks and expectations for Preload -func (r *Repository) ExpectPreload(field string, queriers ...rel.Querier) *Preload { - return ExpectPreload(r, field, queriers) -} - -// Exec raw statement. -// Returns last inserted id, rows affected and error. -func (r *Repository) Exec(ctx context.Context, statement string, args ...interface{}) (int, int, error) { - ret := r.mock.Called(fetchContext(ctx), statement, args) - return ret.Int(0), ret.Int(1), ret.Error(2) -} - -// MustExec raw statement. -// Returns last inserted id, rows affected and error. -func (r *Repository) MustExec(ctx context.Context, statement string, args ...interface{}) (int, int) { - lastInsertedId, rowsAffected, err := r.Exec(ctx, statement, args...) - must(err) - return lastInsertedId, rowsAffected -} - -// ExpectExec for mocking Exec -func (r *Repository) ExpectExec(statement string, args []interface{}) *Exec { - return ExpectExec(r, statement, args) -} - -// Transaction provides a mock function with given fields: fn -func (r *Repository) Transaction(ctx context.Context, fn func(ctx context.Context) error) error { - ctxData := fetchContext(ctx) - r.mock.Called(ctxData) - - var err error - func() { - defer func() { - if p := recover(); p != nil { - switch e := p.(type) { - case runtime.Error: - panic(e) - case error: - err = e - default: - panic(e) - } - } - }() - - ctxData.txDepth++ - ctx = wrapContext(ctx, ctxData) - err = fn(ctx) - }() - - return err -} - -// ExpectTransaction declare expectation inside transaction. -func (r *Repository) ExpectTransaction(fn func(*Repository)) { - r.mock.On("Transaction", r.ctxData).Once() - - r.ctxData.txDepth++ - fn(r) - r.ctxData.txDepth-- -} - -// AssertExpectations asserts that everything was in fact called as expected. Calls may have occurred in any order. -func (r *Repository) AssertExpectations(t *testing.T) bool { - return r.mock.AssertExpectations(t) -} - -// New test repository. -// -// Deprecated: Use github.com/go-rel/reltest instead. -func New() *Repository { - return &Repository{ - repo: rel.New(&nopAdapter{}), - } -} - -func must(err error) { - if err != nil { - panic(err) - } -} diff --git a/reltest/repository_test.go b/reltest/repository_test.go deleted file mode 100644 index 4c98dff1..00000000 --- a/reltest/repository_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package reltest - -import ( - "context" - "database/sql" - "testing" - - "github.com/go-rel/rel" - "github.com/go-rel/rel/where" - "github.com/stretchr/testify/assert" -) - -type Author struct { - ID int - Name string - Books []Book -} - -type Rating struct { - ID int - Score int - BookID int - Book *Book -} - -type Poster struct { - ID int - Image string - BookID int -} - -type Book struct { - ID int - Title string - Author Author - AuthorID *int - Ratings []Rating `auto:"true"` - Poster Poster `autosave:"true"` - AbstractID int - Abstract Abstract `autosave:"true"` - Views int -} - -type Abstract struct { - ID int - Content string -} - -func TestRepository_Adapter(t *testing.T) { - var ( - ctx = context.TODO() - repo = New() - ) - - assert.NotNil(t, repo.Adapter(ctx)) -} - -func TestRepository_Instrumentation(t *testing.T) { - assert.NotPanics(t, func() { - New().Instrumentation(rel.DefaultLogger) - }) -} - -func TestRepository_Ping(t *testing.T) { - assert.Nil(t, New().Ping(context.TODO())) -} - -func TestRepository_Transaction(t *testing.T) { - var ( - repo = New() - result = Book{Title: "Golang for dummies"} - book = Book{ID: 1, Title: "Golang for dummies", Ratings: []Rating{}} - ) - - repo.ExpectTransaction(func(repo *Repository) { - repo.ExpectInsert() - - repo.ExpectTransaction(func(repo *Repository) { - repo.ExpectFind(where.Eq("id", 1)) - - repo.ExpectTransaction(func(repo *Repository) { - repo.ExpectDelete() - }) - }) - }) - - assert.Nil(t, repo.Transaction(context.TODO(), func(ctx context.Context) error { - repo.MustInsert(ctx, &result) - - return repo.Transaction(ctx, func(ctx context.Context) error { - repo.MustFind(ctx, &result, where.Eq("id", 1)) - - return repo.Transaction(ctx, func(ctx context.Context) error { - return repo.Delete(ctx, &result) - }) - }) - })) - - assert.Equal(t, book, result) - repo.AssertExpectations(t) -} - -func TestRepository_Transaction_error(t *testing.T) { - var ( - repo = New() - result = Book{Title: "Golang for dummies"} - book = Book{ID: 1, Title: "Golang for dummies"} - ) - - repo.ExpectTransaction(func(repo *Repository) { - repo.ExpectInsert().ConnectionClosed() - }) - - assert.Equal(t, sql.ErrConnDone, repo.Transaction(context.TODO(), func(ctx context.Context) error { - repo.MustInsert(ctx, &result) - return nil - })) - - assert.Equal(t, book, result) - repo.AssertExpectations(t) -} - -func TestRepository_Transaction_panic(t *testing.T) { - var ( - repo = New() - ) - - repo.ExpectTransaction(func(repo *Repository) { - }) - - assert.Panics(t, func() { - _ = repo.Transaction(context.TODO(), func(ctx context.Context) error { - panic("error") - }) - }) - - repo.AssertExpectations(t) -} - -func TestRepository_Transaction_runtimerError(t *testing.T) { - var ( - book *Book - repo = New() - ) - - repo.ExpectTransaction(func(repo *Repository) { - }) - - assert.Panics(t, func() { - _ = repo.Transaction(context.TODO(), func(ctx context.Context) error { - _ = book.ID - return nil - }) - }) - - repo.AssertExpectations(t) -}