package payment import ( "encoding/json" "net/http/httptest" "testing" "github.com/DATA-DOG/go-sqlmock" "github.com/gin-gonic/gin" ) func TestListRechargeBillAppsReturnsStoredLogoURL(t *testing.T) { gin.SetMode(gin.TestMode) db, mock, err := sqlmock.New() if err != nil { t.Fatalf("create sqlmock: %v", err) } defer db.Close() mock.ExpectQuery(`SELECT app_code, app_name, logo_url`). WillReturnRows(sqlmock.NewRows([]string{"app_code", "app_name", "logo_url"}). AddRow("lalu", "Lalu", "https://media.haiyihy.com/admin/apps/logos/lalu.png")) recorder := httptest.NewRecorder() // 直接使用 recorder 承载 Gin 响应,测试只关注 App 目录映射,不绕过真实 handler 序列化。 context, _ := gin.CreateTestContext(recorder) context.Request = httptest.NewRequest("GET", "/api/v1/admin/payment/recharge-apps", nil) (&Handler{userDB: db, billSources: map[string]RechargeBillSource{}}).ListRechargeBillApps(context) if recorder.Code != 200 { t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String()) } var payload struct { Data struct { Items []rechargeBillAppDTO `json:"items"` } `json:"data"` } if err := json.Unmarshal(recorder.Body.Bytes(), &payload); err != nil { t.Fatalf("decode response: %v", err) } if len(payload.Data.Items) != 1 || payload.Data.Items[0].LogoURL != "https://media.haiyihy.com/admin/apps/logos/lalu.png" { t.Fatalf("unexpected apps: %+v", payload.Data.Items) } if err := mock.ExpectationsWereMet(); err != nil { t.Fatalf("sql expectations: %v", err) } }