Files
ResolveSpec/pkg/reflection/model_utils_foreign_key_test.go
Hein cd65946191 fix(database): add Scan method to insert query interfaces
* Implement Scan method for BunInsertQuery, GormInsertQuery, and PgSQLInsertQuery
* Update mock implementations to support Scan method
* Introduce GetForeignKeyColumn utility for foreign key resolution
* Add tests for GetForeignKeyColumn functionality
2026-05-18 12:04:50 +02:00

124 lines
3.2 KiB
Go

package reflection
import (
"reflect"
"testing"
)
// --- local test models ---
type fkDept struct{}
// bunEmployee uses bun join: tag to declare the FK column explicitly.
type bunEmployee struct {
DeptID string `bun:"dept_id" json:"dept_id"`
Department *fkDept `bun:"rel:belongs-to,join:dept_id=id" json:"department"`
}
// gormEmployee uses gorm foreignKey: tag (mirrors testmodels.Employee).
type gormEmployee struct {
DepartmentID string `json:"department_id"`
ManagerID string `json:"manager_id"`
Department *fkDept `gorm:"foreignKey:DepartmentID;references:ID" json:"department"`
Manager *fkDept `gorm:"foreignKey:ManagerID;references:ID" json:"manager"`
}
// conventionEmployee has no explicit FK tag — relies on naming convention.
type conventionEmployee struct {
DepartmentID string `json:"department_id"`
Department *fkDept `json:"department"`
}
// noTagEmployee has a relation field with no FK tag and no convention match.
type noTagEmployee struct {
Unrelated *fkDept `json:"unrelated"`
}
func TestGetForeignKeyColumn(t *testing.T) {
tests := []struct {
name string
modelType reflect.Type
parentKey string
want string
}{
// Bun join: tag
{
name: "bun join tag returns local column",
modelType: reflect.TypeOf(bunEmployee{}),
parentKey: "department",
want: "dept_id",
},
{
name: "bun join tag matched via json tag (case-insensitive)",
modelType: reflect.TypeOf(bunEmployee{}),
parentKey: "Department",
want: "dept_id",
},
// GORM foreignKey: tag
{
name: "gorm foreignKey resolves to column name",
modelType: reflect.TypeOf(gormEmployee{}),
parentKey: "department",
want: "department_id",
},
{
name: "gorm foreignKey resolves second relation",
modelType: reflect.TypeOf(gormEmployee{}),
parentKey: "manager",
want: "manager_id",
},
{
name: "gorm foreignKey matched case-insensitively",
modelType: reflect.TypeOf(gormEmployee{}),
parentKey: "Department",
want: "department_id",
},
// Pointer and slice unwrapping
{
name: "pointer to struct is unwrapped",
modelType: reflect.TypeOf(&gormEmployee{}),
parentKey: "department",
want: "department_id",
},
{
name: "slice of struct is unwrapped",
modelType: reflect.TypeOf([]gormEmployee{}),
parentKey: "department",
want: "department_id",
},
// No tag — returns "" so caller can fall back to convention
{
name: "relation with no FK tag returns empty string",
modelType: reflect.TypeOf(conventionEmployee{}),
parentKey: "department",
want: "",
},
// Unknown parent key
{
name: "unknown parent key returns empty string",
modelType: reflect.TypeOf(gormEmployee{}),
parentKey: "nonexistent",
want: "",
},
{
name: "non-struct type returns empty string",
modelType: reflect.TypeOf(""),
parentKey: "department",
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetForeignKeyColumn(tt.modelType, tt.parentKey)
if got != tt.want {
t.Errorf("GetForeignKeyColumn(%v, %q) = %q, want %q", tt.modelType, tt.parentKey, got, tt.want)
}
})
}
}