189 lines
5.6 KiB
Go
189 lines
5.6 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
package repositoryimp_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.sendico.io/tech/sxchnge/shared/database/internal/builder"
|
|
"git.sendico.io/tech/sxchnge/shared/database/internal/repository"
|
|
"git.sendico.io/tech/sxchnge/shared/database/record"
|
|
"git.sendico.io/tech/sxchnge/shared/database/repository/builder"
|
|
"git.sendico.io/tech/sxchnge/shared/errors"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/testcontainers/testcontainers-go"
|
|
"github.com/testcontainers/testcontainers-go/modules/mongodb"
|
|
"github.com/testcontainers/testcontainers-go/wait"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
|
)
|
|
|
|
type TestObject struct {
|
|
storable.Base `bson:",inline" json:",inline"`
|
|
Name string `bson:"name"`
|
|
Tags []string `bson:"tags"`
|
|
}
|
|
|
|
func (t *TestObject) Collection() string {
|
|
return "testObject"
|
|
}
|
|
|
|
type AnotherObject struct {
|
|
storable.Base `bson:",inline" json:",inline"`
|
|
Description string `bson:"description"`
|
|
}
|
|
|
|
func (a *AnotherObject) Collection() string {
|
|
return "anotherObject"
|
|
}
|
|
|
|
func terminate(ctx context.Context, t *testing.T, container *mongodb.MongoDBContainer) {
|
|
err := container.Terminate(ctx)
|
|
require.NoError(t, err, "failed to terminate MongoDB container")
|
|
}
|
|
|
|
func disconnect(ctx context.Context, t *testing.T, client *mongo.Client) {
|
|
err := client.Disconnect(ctx)
|
|
require.NoError(t, err, "failed to disconnect from MongoDB")
|
|
}
|
|
|
|
func TestMongoRepository_Get(t *testing.T) {
|
|
// Use a context with timeout, so if container spinning or DB ops hang,
|
|
// the test won't run indefinitely.
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
|
defer cancel()
|
|
|
|
mongoContainer, err := mongodb.Run(ctx,
|
|
"mongo:latest",
|
|
mongodb.WithUsername("root"),
|
|
mongodb.WithPassword("password"),
|
|
testcontainers.WithWaitStrategy(wait.ForLog("Waiting for connections")),
|
|
)
|
|
require.NoError(t, err, "failed to start MongoDB container")
|
|
defer terminate(ctx, t, mongoContainer)
|
|
|
|
mongoURI, err := mongoContainer.ConnectionString(ctx)
|
|
require.NoError(t, err, "failed to get MongoDB connection string")
|
|
|
|
clientOptions := options.Client().ApplyURI(mongoURI)
|
|
client, err := mongo.Connect(clientOptions)
|
|
require.NoError(t, err, "failed to connect to MongoDB")
|
|
defer disconnect(ctx, t, client)
|
|
|
|
db := client.Database("testdb")
|
|
repository := repositoryimp.NewMongoRepository(db, "testcollection")
|
|
|
|
t.Run("Get_Success", func(t *testing.T) {
|
|
testObj := &TestObject{Name: "testName"}
|
|
err := repository.Insert(ctx, testObj, nil)
|
|
require.NoError(t, err)
|
|
|
|
result := &TestObject{}
|
|
err = repository.Get(ctx, testObj.ID, result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, testObj.Name, result.Name)
|
|
assert.Equal(t, testObj.ID, result.ID)
|
|
})
|
|
|
|
t.Run("Get_NotFound", func(t *testing.T) {
|
|
nonExistentID := bson.NewObjectID()
|
|
result := &TestObject{}
|
|
|
|
err := repository.Get(ctx, nonExistentID, result)
|
|
assert.Error(t, err)
|
|
assert.True(t, errors.Is(err, merrors.ErrNoData))
|
|
})
|
|
|
|
t.Run("Get_InvalidID", func(t *testing.T) {
|
|
invalidID := bson.ObjectID{} // zero value
|
|
result := &TestObject{}
|
|
|
|
err := repository.Get(ctx, invalidID, result)
|
|
assert.Error(t, err)
|
|
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
|
|
})
|
|
|
|
t.Run("Get_DifferentTypes", func(t *testing.T) {
|
|
anotherObj := &AnotherObject{Description: "testDescription"}
|
|
err := repository.Insert(ctx, anotherObj, nil)
|
|
require.NoError(t, err)
|
|
|
|
result := &AnotherObject{}
|
|
err = repository.Get(ctx, anotherObj.ID, result)
|
|
require.NoError(t, err)
|
|
assert.Equal(t, anotherObj.Description, result.Description)
|
|
assert.Equal(t, anotherObj.ID, result.ID)
|
|
})
|
|
}
|
|
|
|
func TestMongoRepository_ListIDs(t *testing.T) {
|
|
// Use a context with timeout, so if container spinning or DB ops hang,
|
|
// the test won't run indefinitely.
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
|
defer cancel()
|
|
|
|
mongoContainer, err := mongodb.Run(ctx,
|
|
"mongo:latest",
|
|
mongodb.WithUsername("root"),
|
|
mongodb.WithPassword("password"),
|
|
testcontainers.WithWaitStrategy(wait.ForLog("Waiting for connections")),
|
|
)
|
|
require.NoError(t, err, "failed to start MongoDB container")
|
|
defer terminate(ctx, t, mongoContainer)
|
|
|
|
mongoURI, err := mongoContainer.ConnectionString(ctx)
|
|
require.NoError(t, err, "failed to get MongoDB connection string")
|
|
|
|
clientOptions := options.Client().ApplyURI(mongoURI)
|
|
client, err := mongo.Connect(clientOptions)
|
|
require.NoError(t, err, "failed to connect to MongoDB")
|
|
defer disconnect(ctx, t, client)
|
|
|
|
db := client.Database("testdb")
|
|
repository := repositoryimp.NewMongoRepository(db, "testcollection")
|
|
|
|
t.Run("ListIDs_Success", func(t *testing.T) {
|
|
// Insert test data
|
|
testObjs := []*TestObject{
|
|
{Name: "testName1"},
|
|
{Name: "testName2"},
|
|
{Name: "testName3"},
|
|
}
|
|
for _, obj := range testObjs {
|
|
err := repository.Insert(ctx, obj, nil)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// Define a query to match all objects
|
|
query := builderimp.NewQueryImp()
|
|
|
|
// Call ListIDs
|
|
ids, err := repository.ListIDs(ctx, query)
|
|
require.NoError(t, err)
|
|
|
|
// Assert the IDs are correct
|
|
require.Len(t, ids, len(testObjs))
|
|
for _, obj := range testObjs {
|
|
assert.Contains(t, ids, obj.ID)
|
|
}
|
|
})
|
|
|
|
t.Run("ListIDs_EmptyResult", func(t *testing.T) {
|
|
// Define a query that matches no objects
|
|
query := builderimp.NewQueryImp().Comparison(builderimp.NewFieldImp("name"), builder.Eq, "nonExistentName")
|
|
|
|
// Call ListIDs
|
|
ids, err := repository.ListIDs(ctx, query)
|
|
require.NoError(t, err)
|
|
|
|
// Assert no IDs are returned
|
|
assert.Empty(t, ids)
|
|
})
|
|
}
|