Refactor repository
This commit is contained in:
parent
f1c6820d66
commit
2716580834
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
"go.mongodb.org/mongo-driver/bson"
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
driver "go.mongodb.org/mongo-driver/mongo"
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
"go.mongodb.org/mongo-driver/mongo/options"
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,11 +28,11 @@ type RepositoryInterface[T Document] interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Repository[T Document] struct {
|
type Repository[T Document] struct {
|
||||||
collection *driver.Collection
|
collection *mongo.Collection
|
||||||
indexes []driver.IndexModel
|
indexes []mongo.IndexModel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepository[T Document](collection *driver.Collection, indexes []driver.IndexModel) *Repository[T] {
|
func NewRepository[T Document](collection *mongo.Collection, indexes []mongo.IndexModel) *Repository[T] {
|
||||||
return &Repository[T]{collection: collection, indexes: withTimestampIndexes(indexes)}
|
return &Repository[T]{collection: collection, indexes: withTimestampIndexes(indexes)}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,6 +112,6 @@ func (s *Repository[T]) EnsureIndexes(ctx context.Context, createIndexes bool) (
|
|||||||
return ensureIndexes(ctx, s.collection, s.indexes, createIndexes)
|
return ensureIndexes(ctx, s.collection, s.indexes, createIndexes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func repositoryError(collection *driver.Collection, op string, err error) error {
|
func repositoryError(collection *mongo.Collection, op string, err error) error {
|
||||||
return fmt.Errorf("%s.%s: %v", collection.Name(), op, err)
|
return fmt.Errorf("%s.%s: %v", collection.Name(), op, err)
|
||||||
}
|
}
|
||||||
|
195
repository_test.go
Normal file
195
repository_test.go
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
package leaf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/integration/mtest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tModel struct {
|
||||||
|
Name string `bson:"name"`
|
||||||
|
Base `bson:",inline"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func tModelToBSON(model *tModel) bson.D {
|
||||||
|
raw, _ := bson.Marshal(model)
|
||||||
|
|
||||||
|
var doc bson.D
|
||||||
|
bson.Unmarshal(raw, &doc)
|
||||||
|
|
||||||
|
return doc
|
||||||
|
}
|
||||||
|
|
||||||
|
func tModelsToBSON(models []*tModel) []bson.D {
|
||||||
|
docs := make([]bson.D, len(models))
|
||||||
|
for i := range models {
|
||||||
|
docs[i] = tModelToBSON(models[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
return docs
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_Find(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("returns data on success", func(mt *mtest.T) {
|
||||||
|
data := []*tModel{{Name: "test1"}, {Name: "test2"}}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses(mtest.CreateCursorResponse(0, "test.foo", mtest.FirstBatch, tModelsToBSON(data)...))
|
||||||
|
result, err := repo.Find(ctx, bson.M{})
|
||||||
|
assert.Nil(mt, err)
|
||||||
|
assert.Equal(mt, data, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_FindOne(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("returns data on success", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses((mtest.CreateCursorResponse(0, "test.foo", mtest.FirstBatch, tModelToBSON(data))))
|
||||||
|
result, err := repo.FindOne(ctx, bson.M{"name": "test"})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, data, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
mt.Run("returns error on failure", func(mt *mtest.T) {
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses((mtest.CreateCursorResponse(0, "test.foo", mtest.FirstBatch)))
|
||||||
|
_, err := repo.FindOne(ctx, bson.M{"name": "test"})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_FindByID(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("returns data on success", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Base: Base{ObjectID: primitive.NewObjectID()}, Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses(mtest.CreateCursorResponse(0, "test.foo", mtest.FirstBatch, tModelToBSON(data)))
|
||||||
|
result, err := repo.FindByID(ctx, data.ID().Hex())
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, data, result)
|
||||||
|
})
|
||||||
|
|
||||||
|
mt.Run("returns error on failure", func(mt *mtest.T) {
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses(mtest.CreateCursorResponse(0, "test.foo", mtest.FirstBatch))
|
||||||
|
_, err := repo.FindByID(ctx, "invalid")
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_Create(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("creates a new document successfully", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses(mtest.CreateSuccessResponse())
|
||||||
|
result, err := repo.Create(ctx, data)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotEmpty(t, result.ObjectID)
|
||||||
|
assert.WithinDuration(t, time.Now(), result.CreatedAt, time.Second)
|
||||||
|
assert.WithinDuration(t, time.Now(), result.UpdatedAt, time.Second)
|
||||||
|
})
|
||||||
|
|
||||||
|
mt.Run("returns error on failure", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
errResponse := mtest.CreateWriteErrorsResponse(mtest.WriteError{Index: 0, Code: 11000, Message: "duplicate key error"})
|
||||||
|
mt.AddMockResponses(errResponse)
|
||||||
|
_, err := repo.Create(ctx, data)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_UpdateOne(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("updates a document successfully", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
successResponse := mtest.CreateSuccessResponse(
|
||||||
|
bson.E{Key: "n", Value: 1},
|
||||||
|
bson.E{Key: "nModified", Value: 1},
|
||||||
|
)
|
||||||
|
|
||||||
|
mt.AddMockResponses(successResponse)
|
||||||
|
result, err := repo.UpdateOne(ctx, bson.M{"name": "test"}, data)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, data, result)
|
||||||
|
assert.WithinDuration(t, time.Now(), result.UpdatedAt, time.Second)
|
||||||
|
})
|
||||||
|
|
||||||
|
mt.Run("returns error on failure", func(mt *mtest.T) {
|
||||||
|
data := &tModel{Name: "test"}
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
errResponse := mtest.CreateWriteErrorsResponse(mtest.WriteError{Index: 0, Code: 11000, Message: "duplicate key error"})
|
||||||
|
mt.AddMockResponses(errResponse)
|
||||||
|
_, err := repo.UpdateOne(ctx, bson.M{"name": "test"}, data)
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_DeleteOne(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("deletes a document successfully", func(mt *mtest.T) {
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
successResponse := mtest.CreateSuccessResponse(
|
||||||
|
bson.E{Key: "n", Value: 1},
|
||||||
|
)
|
||||||
|
|
||||||
|
mt.AddMockResponses(successResponse)
|
||||||
|
err := repo.DeleteOne(ctx, bson.M{"name": "test"})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
mt.Run("returns error on failure", func(mt *mtest.T) {
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
errResponse := mtest.CreateWriteErrorsResponse(mtest.WriteError{Index: 0, Code: 11000, Message: "delete error"})
|
||||||
|
mt.AddMockResponses(errResponse)
|
||||||
|
err := repo.DeleteOne(ctx, bson.M{"name": "test"})
|
||||||
|
assert.NotNil(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_CountDocuments(t *testing.T) {
|
||||||
|
mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
mt.Run("returns count on success", func(mt *mtest.T) {
|
||||||
|
repo := NewRepository[*tModel](mt.Coll, []mongo.IndexModel{})
|
||||||
|
|
||||||
|
mt.AddMockResponses(mtest.CreateCursorResponse(1, "test.foo", mtest.FirstBatch, bson.D{bson.E{Key: "n", Value: 2}}))
|
||||||
|
count, err := repo.CountDocuments(ctx, bson.M{"name": "test"})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 2, count)
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user