From 980eda29af834f600011a34da50adae107470f4c Mon Sep 17 00:00:00 2001 From: Thomas Peetz Date: Tue, 6 Oct 2026 17:11:42 +0200 Subject: [PATCH] add tests for repository --- kontor-gin/go.mod | 4 +- kontor-gin/internal/handlers/sport.go | 2 +- kontor-gin/internal/main_test.go | 16 ++++- kontor-gin/internal/repository/sport.go | 20 ++++-- kontor-gin/internal/service/sport.go | 4 +- kontor-gin/internal/tests/repository.go | 65 +++++++++++++++++++ kontor-gin/internal/tests/service.go | 45 +++++++++++++ .../tests/testutils/db_test_helper.go | 10 +-- .../internal/{helpers => tests}/time_test.go | 5 +- 9 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 kontor-gin/internal/tests/repository.go create mode 100644 kontor-gin/internal/tests/service.go rename kontor-gin/internal/{helpers => tests}/time_test.go (93%) diff --git a/kontor-gin/go.mod b/kontor-gin/go.mod index ac8ba72..f551c3b 100644 --- a/kontor-gin/go.mod +++ b/kontor-gin/go.mod @@ -12,9 +12,11 @@ require ( github.com/google/uuid v1.6.0 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 + github.com/stretchr/testify v1.12.1 golang.org/x/crypto v0.57.0 golang.org/x/time v0.16.0 gorm.io/driver/postgres v1.6.3 + gorm.io/driver/sqlite v1.6.0 gorm.io/gorm v1.31.2 resty.dev/v3 v3.0.0-rc.4 ) @@ -48,6 +50,7 @@ require ( github.com/klauspost/cpuid/v2 v2.4.0 // indirect github.com/leodido/go-urn v1.5.0 // indirect github.com/mattn/go-isatty v0.0.24 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.4.3 // indirect @@ -57,7 +60,6 @@ require ( github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect github.com/spf13/pflag v1.0.10 // indirect - github.com/stretchr/testify v1.12.1 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.2 // indirect diff --git a/kontor-gin/internal/handlers/sport.go b/kontor-gin/internal/handlers/sport.go index fb71b5d..5db3b3a 100644 --- a/kontor-gin/internal/handlers/sport.go +++ b/kontor-gin/internal/handlers/sport.go @@ -15,7 +15,7 @@ type SportHandler struct { } func (handler *SportHandler) List(c *gin.Context) { - sports, err := handler.Service.List(c.Request.Context()) + sports, _, err := handler.Service.List(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return diff --git a/kontor-gin/internal/main_test.go b/kontor-gin/internal/main_test.go index e84d3ff..a2eb349 100644 --- a/kontor-gin/internal/main_test.go +++ b/kontor-gin/internal/main_test.go @@ -3,9 +3,23 @@ package internal import ( "testing" - "kontor-api-gin/internal/test/testutils" + "kontor-api-gin/internal/tests" + "kontor-api-gin/internal/tests/testutils" + + "github.com/stretchr/testify/suite" + "gorm.io/gorm" ) +var TestDB *gorm.DB + func TestMain(m *testing.M) { testutils.InitializeTestSuite(m) } + +func TestRepos(t *testing.T) { + suite.Run(t, new(tests.RepositoryTestSuite)) +} + +func TestServices(t *testing.T) { + suite.Run(t, new(tests.ServiceTestSuite)) +} diff --git a/kontor-gin/internal/repository/sport.go b/kontor-gin/internal/repository/sport.go index 8b8d613..7c1e012 100644 --- a/kontor-gin/internal/repository/sport.go +++ b/kontor-gin/internal/repository/sport.go @@ -17,13 +17,21 @@ func NewSportRepository(db *gorm.DB) *SportRepository { return repo } -func (repository *SportRepository) FindAll(context context.Context) ([]models.Sport, error) { - var sports []models.Sport +func (repository *SportRepository) FindAll(page int, limit int, context context.Context) (sports []models.Sport, total int64, err error) { + offset := (page - 1) * limit - result := repository.db.Find(&sports) - slog.Info("SportRepository#FindAll", "count", result.RowsAffected) - - return sports, nil + err = repository.db. + Model(&models.Sport{}). + Count(&total). + Limit(limit). + Offset(offset). + Order("id asc"). + Find(&sports).Error + if err != nil { + return + } + slog.Info("SportRepository#FindAll", "total", total) + return } func (repository *SportRepository) GetById(context context.Context, id string) (models.Sport, error) { diff --git a/kontor-gin/internal/service/sport.go b/kontor-gin/internal/service/sport.go index b91653e..66a8430 100644 --- a/kontor-gin/internal/service/sport.go +++ b/kontor-gin/internal/service/sport.go @@ -16,9 +16,9 @@ func NewSportService(repo *repository.SportRepository) *SportService { return service } -func (service *SportService) List(context context.Context) ([]models.Sport, error) { +func (service *SportService) List(context context.Context) ([]models.Sport, int64, error) { slog.Info("SportService#List") - return service.repository.FindAll(context) + return service.repository.FindAll(1, 10, context) } func (service *SportService) Get(context context.Context, id string) (models.Sport, error) { diff --git a/kontor-gin/internal/tests/repository.go b/kontor-gin/internal/tests/repository.go new file mode 100644 index 0000000..e58256e --- /dev/null +++ b/kontor-gin/internal/tests/repository.go @@ -0,0 +1,65 @@ +package tests + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "log/slog" + "os" + + "github.com/stretchr/testify/suite" + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +var testDB *gorm.DB + +type RepositoryTestSuite struct { + suite.Suite +} + +func (suite *RepositoryTestSuite) TestSportFindAll() { + sportRepository := repository.NewSportRepository(testDB) + _, total, err := sportRepository.FindAll(1, 10, context.Background()) + suite.Nil(err) + suite.Equal(int64(0), total) +} + +// This will run right before the test starts +// and receives the suite and test names as input +func (suite *RepositoryTestSuite) BeforeTest(suiteName, testName string) { + slog.Info("RepositoryTestSuite#BeforeTest", "suiteName", suiteName, "testName", testName) +} + +// This will run after test finishes +// and receives the suite and test names as input +func (suite *RepositoryTestSuite) AfterTest(suiteName, testName string) { + slog.Info("RepositoryTestSuite#AfterTest", "suiteName", suiteName, "testName", testName) +} + +// This will run before before the tests in the suite are run +func (suite *RepositoryTestSuite) SetupSuite() { + slog.Info("RepositoryTestSuite#SetupSuite") + // Remove existing test db to ensure clean state + os.Remove("test.db") + + db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) + if err != nil { + panic("failed to connect test database") + } + + // Auto-migrate models to ensure schema matches + db.AutoMigrate(&models.Sport{}) + + testDB = db +} + +// This will run before before the tests in the suite are run +func (suite *RepositoryTestSuite) TearDownSuite() { + slog.Info("RepositoryTestSuite#TeardownSuite") +} + +// This will run before each test in the suite +func (suite *RepositoryTestSuite) SetupTest() { + slog.Info("RepositoryTestSuite#SetupTest") +} diff --git a/kontor-gin/internal/tests/service.go b/kontor-gin/internal/tests/service.go new file mode 100644 index 0000000..3562a72 --- /dev/null +++ b/kontor-gin/internal/tests/service.go @@ -0,0 +1,45 @@ +package tests + +import ( + "context" + "kontor-api-gin/internal/models" + "kontor-api-gin/internal/repository" + "kontor-api-gin/internal/service" + "log/slog" + "os" + + "github.com/stretchr/testify/suite" + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +var testServiceDB *gorm.DB + +type ServiceTestSuite struct { + suite.Suite +} + +func (suite *ServiceTestSuite) TestSportServiceList() { + sportService := service.NewSportService(repository.NewSportRepository(testServiceDB)) + sports, total, err := sportService.List(context.Background()) + suite.Nil(err) + suite.Equal(int64(0), total) + suite.Equal(0, len(sports)) +} + +// This will run before before the tests in the suite are run +func (suite *ServiceTestSuite) SetupSuite() { + slog.Info("RepositoryTestSuite#SetupSuite") + // Remove existing test db to ensure clean state + os.Remove("test.db") + + db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) + if err != nil { + panic("failed to connect test database") + } + + // Auto-migrate models to ensure schema matches + db.AutoMigrate(&models.Sport{}) + + testServiceDB = db +} diff --git a/kontor-gin/internal/tests/testutils/db_test_helper.go b/kontor-gin/internal/tests/testutils/db_test_helper.go index f451654..ace3973 100644 --- a/kontor-gin/internal/tests/testutils/db_test_helper.go +++ b/kontor-gin/internal/tests/testutils/db_test_helper.go @@ -1,27 +1,29 @@ package testutils import ( + "log/slog" "os" "testing" ) func SetupTestDatabase() { - + slog.Info("SetupTestDatabase") } func PatchDatabase() { - + slog.Info("PatchDatabase") } func TearDownTestDatabase() { - + slog.Info("TearDownTestDatabase") } func UnpatchDatabase() { - + slog.Info("UnpatchDatabase") } func InitializeTestSuite(m *testing.M) { + slog.Info("InitializeTestSuite") // Initialize the test database SetupTestDatabase() // Patch the global database.DB to use the TestDB diff --git a/kontor-gin/internal/helpers/time_test.go b/kontor-gin/internal/tests/time_test.go similarity index 93% rename from kontor-gin/internal/helpers/time_test.go rename to kontor-gin/internal/tests/time_test.go index b4590b9..b876adb 100644 --- a/kontor-gin/internal/helpers/time_test.go +++ b/kontor-gin/internal/tests/time_test.go @@ -1,7 +1,8 @@ -package helpers +package tests import ( "encoding/json" + "kontor-api-gin/internal/helpers" "testing" ) @@ -40,7 +41,7 @@ func TestMultiFormatTimeUnmarshal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - var m KontorTime + var m helpers.KontorTime err := json.Unmarshal([]byte(tt.input), &m) if (err != nil) != tt.wantErr { t.Errorf("UnmarshalJSON() error = %v, wantErr %v", err, tt.wantErr)