You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

69 lines
2.2 KiB

package email
import "testing"
// 热重载的核心安全属性:后台填错配置时,Reload 必须「返回 error + 保留旧客户端 + 不 panic」,
// 绝不能让线上服务失去发信能力。(OnInit 走的是 panic 路径,仅用于启动。)
func TestReloadBadConfigKeepsOldClient(t *testing.T) {
if err := OnInit(map[string]interface{}{
"EmailType": 1, "FromEmail": "a@example.com", "FromName": "Old", "Password": "pw",
}); err != nil {
t.Fatalf("OnInit 失败: %v", err)
}
old := get()
if old == nil {
t.Fatal("OnInit 后客户端不应为 nil")
}
cases := []struct {
name string
cfg map[string]interface{}
}{
{"FromEmail 是裸域名(Resend 会 422 拒绝)", map[string]interface{}{
"EmailType": 3, "FromEmail": "mail.example.com", "Password": "re_x"}},
{"Password 为空", map[string]interface{}{
"EmailType": 1, "FromEmail": "a@example.com"}},
{"FromEmail 为空", map[string]interface{}{
"EmailType": 1, "Password": "pw"}},
}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
if err := Reload(c.cfg); err == nil {
t.Fatal("非法配置必须返回 error")
}
if get() != old {
t.Fatal("重载失败后必须保留旧客户端")
}
})
}
}
// 合法配置应当整体热替换客户端,且能在 SMTP ↔ Resend 两种不同具体类型间切换。
func TestReloadSwapsClient(t *testing.T) {
if err := OnInit(map[string]interface{}{
"EmailType": 1, "FromEmail": "a@example.com", "Password": "pw",
}); err != nil {
t.Fatalf("OnInit 失败: %v", err)
}
old := get()
if _, ok := old.(*Email); !ok {
t.Fatalf("EmailType=1 应为 *Email,实得 %T", old)
}
if err := Reload(map[string]interface{}{
"EmailType": 3, "FromEmail": "noreply@mail.example.com", "FromName": "New", "Password": "re_x",
}); err != nil {
t.Fatalf("合法配置重载应成功: %v", err)
}
cur := get()
if cur == old {
t.Fatal("重载成功后应替换为新客户端")
}
r, ok := cur.(*Resend)
if !ok {
t.Fatalf("EmailType=3 应为 *Resend,实得 %T", cur)
}
if r.ApiKey != "re_x" || r.From != "noreply@mail.example.com" || r.Name != "New" {
t.Fatalf("新客户端未取到新配置: %+v", r)
}
}