test(supply-api): validate shipped config samples

Add regression tests for the shipped development and SMS sample configs, and fix the SMS example to match the runtime flat Config schema instead of nested provider blocks. Verified with fresh go test runs for ./internal/config and ./internal/sms before commit.
This commit is contained in:
Your Name
2026-04-11 11:31:05 +08:00
parent 2bc4a00ecd
commit 5ea6750cf3
4 changed files with 160 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# Supply API Development Configuration
server:
addr: ":18082"
read_timeout: 10s
write_timeout: 15s
idle_timeout: 30s
shutdown_timeout: 5s
database:
host: "localhost"
port: 5432
user: "postgres"
password: ""
database: "supply_db"
max_open_conns: 25
max_idle_conns: 5
conn_max_lifetime: 1h
conn_max_idle_time: 10m
redis:
host: "localhost"
port: 6379
password: ""
db: 0
pool_size: 10
token:
secret_key: "${SUPPLY_TOKEN_SECRET_KEY}"
issuer: "lijiaoqiao/supply-api"
access_token_ttl: 1h
refresh_token_ttl: 168h
revocation_cache_ttl: 30s
audit:
buffer_size: 1000
flush_interval: 5s
export_timeout: 30s

View File

@@ -0,0 +1,47 @@
# SMS Service Configuration
# 短信服务配置
sms:
# 是否启用SMS服务默认 false 时运行时会拒绝验证码校验
enabled: false
# SMS服务提供商: tencent (腾讯云) 或 aliyun (阿里云)
provider: tencent
# 运行时读取扁平字段,而不是按 provider 分组的嵌套字段
app_id: "1400123456" # 腾讯云: SDK AppID阿里云: AccessKey ID
app_secret: "your_app_key" # 腾讯云: AppKey阿里云: AccessKey Secret
sign_name: "供应链平台" # 短信签名
template_code: "SMS_123456789" # 短信模板 CODE
region: "ap-guangzhou" # 腾讯云区域;阿里云可忽略
endpoint: "" # 自定义 endpoint可选
# 通用配置
code_length: 6 # 验证码长度默认6位
code_expire_mins: 5 # 验证码有效期(分钟)默认5分钟
# 示例启用腾讯云SMS
# sms:
# enabled: true
# provider: tencent
# app_id: "1400123456"
# app_secret: "a1b2c3d4e5f6g7h8i9j0"
# sign_name: "供应链平台"
# template_code: "SMS_123456789"
# region: "ap-guangzhou"
# code_length: 6
# code_expire_mins: 5
# 示例启用阿里云SMS
# sms:
# enabled: true
# provider: aliyun
# app_id: "LTAI5tXXXXXXXXXXXX"
# app_secret: |
# -----BEGIN PRIVATE KEY-----
# MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
# -----END PRIVATE KEY-----
# sign_name: "供应链平台"
# template_code: "SMS_123456789"
# code_length: 6
# code_expire_mins: 5

View File

@@ -0,0 +1,31 @@
package config
import (
"path/filepath"
"testing"
)
func TestDevSampleConfigLoads(t *testing.T) {
configPath := filepath.Join("..", "..", "config", "config.dev.yaml")
cfg, err := LoadFromPath("dev", configPath)
if err != nil {
t.Fatalf("expected dev sample config to load, got error: %v", err)
}
if cfg.Server.Addr != ":18082" {
t.Fatalf("expected addr :18082, got %s", cfg.Server.Addr)
}
if cfg.Database.Host != "localhost" {
t.Fatalf("expected database host localhost, got %s", cfg.Database.Host)
}
if cfg.Redis.Host != "localhost" {
t.Fatalf("expected redis host localhost, got %s", cfg.Redis.Host)
}
if cfg.Token.Issuer != "lijiaoqiao/supply-api" {
t.Fatalf("expected issuer lijiaoqiao/supply-api, got %s", cfg.Token.Issuer)
}
if cfg.Settlement.WithdrawEnabled {
t.Fatal("expected dev sample config to keep withdraw disabled by default")
}
}

View File

@@ -0,0 +1,45 @@
package sms
import (
"os"
"path/filepath"
"testing"
"gopkg.in/yaml.v3"
)
type smsExampleRoot struct {
SMS Config `yaml:"sms"`
}
func TestSMSExampleYAML_MatchesRuntimeConfigShape(t *testing.T) {
path := filepath.Join("..", "..", "config", "sms.example.yaml")
content, err := os.ReadFile(path)
if err != nil {
t.Fatalf("failed to read sms example config: %v", err)
}
var root smsExampleRoot
if err := yaml.Unmarshal(content, &root); err != nil {
t.Fatalf("failed to parse sms example config: %v", err)
}
if root.SMS.Provider != ProviderTencent {
t.Fatalf("expected provider %q, got %q", ProviderTencent, root.SMS.Provider)
}
if root.SMS.CodeLength != 6 {
t.Fatalf("expected code length 6, got %d", root.SMS.CodeLength)
}
if root.SMS.CodeExpireMins != 5 {
t.Fatalf("expected code expiry 5, got %d", root.SMS.CodeExpireMins)
}
if root.SMS.SignName == "" {
t.Fatal("expected sign_name to be populated in example config")
}
if root.SMS.TemplateCode == "" {
t.Fatal("expected template_code to be populated in example config")
}
if root.SMS.Region == "" {
t.Fatal("expected region to be populated in example config")
}
}