Files
sendico/api/ledger/storage/mongo/store/balances_test.go
Stephan D 62a6631b9a
All checks were successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
service backend
2025-11-07 18:35:26 +01:00

286 lines
7.6 KiB
Go

package store
import (
"context"
"errors"
"testing"
"github.com/tech/sendico/ledger/storage"
"github.com/tech/sendico/ledger/storage/model"
"github.com/tech/sendico/pkg/db/repository/builder"
"github.com/tech/sendico/pkg/db/storable"
"github.com/tech/sendico/pkg/merrors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
func TestBalancesStore_Get(t *testing.T) {
ctx := context.Background()
logger := zap.NewNop()
t.Run("Success", func(t *testing.T) {
accountRef := primitive.NewObjectID()
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
balance := result.(*model.AccountBalance)
balance.AccountRef = accountRef
balance.Balance = "1500.50"
balance.Version = 10
return nil
},
}
store := &balancesStore{logger: logger, repo: stub}
result, err := store.Get(ctx, accountRef)
require.NoError(t, err)
assert.NotNil(t, result)
assert.Equal(t, accountRef, result.AccountRef)
assert.Equal(t, "1500.50", result.Balance)
assert.Equal(t, int64(10), result.Version)
})
t.Run("ZeroAccountID", func(t *testing.T) {
stub := &repositoryStub{}
store := &balancesStore{logger: logger, repo: stub}
result, err := store.Get(ctx, primitive.NilObjectID)
require.Error(t, err)
assert.Nil(t, result)
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
})
t.Run("NotFound", func(t *testing.T) {
accountRef := primitive.NewObjectID()
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
return merrors.ErrNoData
},
}
store := &balancesStore{logger: logger, repo: stub}
result, err := store.Get(ctx, accountRef)
require.Error(t, err)
assert.Nil(t, result)
assert.True(t, errors.Is(err, storage.ErrBalanceNotFound))
})
t.Run("FindError", func(t *testing.T) {
accountRef := primitive.NewObjectID()
expectedErr := errors.New("database error")
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
return expectedErr
},
}
store := &balancesStore{logger: logger, repo: stub}
result, err := store.Get(ctx, accountRef)
require.Error(t, err)
assert.Nil(t, result)
assert.Equal(t, expectedErr, err)
})
}
func TestBalancesStore_Upsert(t *testing.T) {
ctx := context.Background()
logger := zap.NewNop()
t.Run("Insert_NewBalance", func(t *testing.T) {
accountRef := primitive.NewObjectID()
var insertedBalance *model.AccountBalance
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
return merrors.ErrNoData // Balance doesn't exist
},
InsertFunc: func(ctx context.Context, object storable.Storable, _ builder.Query) error {
insertedBalance = object.(*model.AccountBalance)
return nil
},
}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: accountRef,
Balance: "1000.00",
Version: 1,
}
err := store.Upsert(ctx, balance)
require.NoError(t, err)
assert.NotNil(t, insertedBalance)
assert.Equal(t, "1000.00", insertedBalance.Balance)
})
t.Run("Update_ExistingBalance", func(t *testing.T) {
accountRef := primitive.NewObjectID()
existingID := primitive.NewObjectID()
var updatedBalance *model.AccountBalance
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
existing := result.(*model.AccountBalance)
existing.SetID(existingID)
existing.AccountRef = accountRef
existing.Balance = "500.00"
existing.Version = 5
return nil
},
UpdateFunc: func(ctx context.Context, object storable.Storable) error {
updatedBalance = object.(*model.AccountBalance)
return nil
},
}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: accountRef,
Balance: "1500.00",
Version: 6,
}
err := store.Upsert(ctx, balance)
require.NoError(t, err)
assert.NotNil(t, updatedBalance)
assert.Equal(t, existingID, *updatedBalance.GetID())
assert.Equal(t, "1500.00", updatedBalance.Balance)
assert.Equal(t, int64(6), updatedBalance.Version)
})
t.Run("NilBalance", func(t *testing.T) {
stub := &repositoryStub{}
store := &balancesStore{logger: logger, repo: stub}
err := store.Upsert(ctx, nil)
require.Error(t, err)
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
})
t.Run("ZeroAccountID", func(t *testing.T) {
stub := &repositoryStub{}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: primitive.NilObjectID,
Balance: "100.00",
}
err := store.Upsert(ctx, balance)
require.Error(t, err)
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
})
t.Run("FindError", func(t *testing.T) {
accountRef := primitive.NewObjectID()
expectedErr := errors.New("database error")
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
return expectedErr
},
}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: accountRef,
Balance: "100.00",
}
err := store.Upsert(ctx, balance)
require.Error(t, err)
assert.Equal(t, expectedErr, err)
})
t.Run("InsertError", func(t *testing.T) {
accountRef := primitive.NewObjectID()
expectedErr := errors.New("insert error")
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
return merrors.ErrNoData // Balance doesn't exist
},
InsertFunc: func(ctx context.Context, object storable.Storable, _ builder.Query) error {
return expectedErr
},
}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: accountRef,
Balance: "100.00",
}
err := store.Upsert(ctx, balance)
require.Error(t, err)
assert.Equal(t, expectedErr, err)
})
t.Run("UpdateError", func(t *testing.T) {
accountRef := primitive.NewObjectID()
existingID := primitive.NewObjectID()
expectedErr := errors.New("update error")
stub := &repositoryStub{
FindOneByFilterFunc: func(ctx context.Context, _ builder.Query, result storable.Storable) error {
existing := result.(*model.AccountBalance)
existing.SetID(existingID)
existing.AccountRef = accountRef
existing.Balance = "500.00"
return nil
},
UpdateFunc: func(ctx context.Context, object storable.Storable) error {
return expectedErr
},
}
store := &balancesStore{logger: logger, repo: stub}
balance := &model.AccountBalance{
AccountRef: accountRef,
Balance: "1500.00",
}
err := store.Upsert(ctx, balance)
require.Error(t, err)
assert.Equal(t, expectedErr, err)
})
}
func TestBalancesStore_IncrementBalance(t *testing.T) {
ctx := context.Background()
logger := zap.NewNop()
t.Run("NotImplemented", func(t *testing.T) {
accountRef := primitive.NewObjectID()
stub := &repositoryStub{}
store := &balancesStore{logger: logger, repo: stub}
err := store.IncrementBalance(ctx, accountRef, "100.00")
require.Error(t, err)
assert.True(t, errors.Is(err, merrors.ErrNotImplemented))
})
t.Run("ZeroAccountID", func(t *testing.T) {
stub := &repositoryStub{}
store := &balancesStore{logger: logger, repo: stub}
err := store.IncrementBalance(ctx, primitive.NilObjectID, "100.00")
require.Error(t, err)
assert.True(t, errors.Is(err, merrors.ErrInvalidArg))
})
}