package repository import ( "database/sql" "log" "regexp" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/stretchr/testify/assert" "gorm.io/driver/postgres" "gorm.io/gorm" ) func NewMockDB() (*sql.DB, *gorm.DB, sqlmock.Sqlmock) { sqldb, mock, err := sqlmock.New() if err != nil { log.Fatalf("An error '%s' was not expected when opening a stub database connection", err) } gormdb, err := gorm.Open(postgres.New(postgres.Config{ WithoutQuotingCheck: true, Conn: sqldb, }), &gorm.Config{}) if err != nil { log.Fatalf("An error '%s' was not expected when opening gorm database", err) } return sqldb, gormdb, mock } type MyModel struct { Id int Value string Count int } func (m MyModel) TableName() string { return "my_models" } type MyModelFilter struct { Id *int `filterfield:"field=id,operator=EQ"` Value *string `filterfield:"field=value,operator=EQ"` Count *int `filterfield:"field=count,operator=GT"` } func TestRepository(t *testing.T) { t.Run("List with simple filter", func(t *testing.T) { sqldb, db, mock := NewMockDB() defer sqldb.Close() repo := RepoBase[MyModel]{} repo.Init(db) id := 123 filter := MyModelFilter{ Id: &id, } sql := "SELECT * FROM my_models WHERE my_models.id = $1" mock.ExpectQuery(regexp.QuoteMeta(sql)).WithArgs(id) _, err := repo.List(filter) assert.Nil(t, err) if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } }) t.Run("List with multiple filter values", func(t *testing.T) { sqldb, db, mock := NewMockDB() defer sqldb.Close() repo := RepoBase[MyModel]{} repo.Init(db) id := 123 count := 456 value := "some value" filter := MyModelFilter{ Id: &id, Value: &value, Count: &count, } sql := "SELECT * FROM my_models WHERE my_models.id = $1 AND my_models.value = $2 AND my_models.count > $3" mock.ExpectQuery(regexp.QuoteMeta(sql)).WithArgs(id, value, count) _, err := repo.List(filter) assert.Nil(t, err) if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } }) }