This commit is contained in:
2026-07-08 21:28:08 +08:00
parent 352ee9eaf2
commit 9f985ea8c7
12 changed files with 2504 additions and 39 deletions

View File

@@ -0,0 +1,345 @@
package dwbg
import (
"encoding/json"
"strings"
"testing"
"tyapi-server/internal/domains/api/dto"
"go.uber.org/zap"
)
func TestEmptySinanReportMarshal(t *testing.T) {
params := dto.DWBG6A2CReq{
Name: "张三",
IDCard: "320321199102011152",
MobileNo: "13812345678",
}
report := emptySinanReport(params)
data, err := json.Marshal(report)
if err != nil {
t.Fatalf("序列化失败: %v", err)
}
var parsed map[string]interface{}
if err := json.Unmarshal(data, &parsed); err != nil {
t.Fatalf("反序列化失败: %v", err)
}
requiredModules := []string{
"baseInfo", "standLiveInfo", "riskPoint", "securityInfo", "antiFraudInfo",
"riskList", "applicationStatistics", "lendingStatistics", "performanceStatistics",
"overdueRecord", "creditDetail", "rentalBehavior", "riskSupervision", "judicialLeaseReport",
}
for _, module := range requiredModules {
if _, ok := parsed[module]; !ok {
t.Errorf("缺少顶层模块: %s", module)
}
}
antiFraud, ok := parsed["antiFraudInfo"].(map[string]interface{})
if !ok {
t.Fatal("antiFraudInfo 类型错误")
}
for _, key := range []string{"moneyLaundering", "deceiver", "gamblerPlayer", "gamblerBanker"} {
if _, exists := antiFraud[key]; !exists {
t.Errorf("antiFraudInfo 缺少键: %s", key)
}
}
rental, ok := parsed["rentalBehavior"].(map[string]interface{})
if !ok {
t.Fatal("rentalBehavior 类型错误")
}
if len(rental) != len(rentalBehaviorFieldNames) {
t.Errorf("rentalBehavior 字段数 = %d, want %d", len(rental), len(rentalBehaviorFieldNames))
}
}
func TestTransformToSinanReportAllNil(t *testing.T) {
params := dto.DWBG6A2CReq{
Name: "张三",
IDCard: "320321199102011152",
MobileNo: "13812345678",
}
apiData := map[string]interface{}{
"YYSY35TA": nil,
"YYSYE7V5": nil,
"YYSYH6F3": nil,
"YYSYP0T4": nil,
"FLXGDEA9": nil,
"FLXG8B4D": nil,
"FLXG7E8F": nil,
"JRZQ5E9F": nil,
"JRZQ1D09": nil,
}
report := transformToSinanReport(apiData, params, zap.NewNop())
if _, err := json.Marshal(report); err != nil {
t.Fatalf("全 nil 数据源仍应可序列化: %v", err)
}
}
func TestTransformToSinanReportWithMockData(t *testing.T) {
params := dto.DWBG6A2CReq{
Name: "黄春丽",
IDCard: "452621197903185522",
MobileNo: "13907764404",
}
apiData := map[string]interface{}{
"YYSYH6F3": map[string]interface{}{
"result": "0",
"sex": "女",
"address": "广西壮族自治区百色地区百色市",
"channel": "cmcc",
},
"YYSYE7V5": map[string]interface{}{
"status": 0,
"channel": "cmcc",
},
"YYSY35TA": map[string]interface{}{
"prov": "广西壮族自治区",
"city": "南宁",
"name": "中国移动",
},
"YYSYP0T4": map[string]interface{}{
"time": "[24,-1)",
},
"FLXG8B4D": map[string]interface{}{
"gamblerBanker": "A",
},
"FLXGDEA9": map[string]interface{}{
"level": "A1,C3",
},
"JRZQ5E9F": map[string]interface{}{
"xyp_cpl0001": "2",
"xyp_cpl0007": "2",
"xyp_cpl0008": "1",
"xyp_cpl0011": "2",
"xyp_cpl0012": "2",
"xyp_cpl0013": "3",
"xyp_cpl0044": "1",
"xyp_cpl0074": "0.56",
"xyp_model_score_mid": "500",
},
"JRZQ1D09": map[string]interface{}{
"m12": map[string]interface{}{
"id": map[string]interface{}{"allnum": "7", "orgnum": "1", "tot_mons": "16"},
"cell": map[string]interface{}{"allnum": "7", "orgnum": "1", "tot_mons": "16"},
},
"idcard_relation_phone": 1,
"phone_relation_idard": 0,
},
}
report := transformToSinanReport(apiData, params, zap.NewNop())
standLive := report["standLiveInfo"].(map[string]interface{})
if standLive["finalAuthResult"] != "0" || standLive["verification"] != "0" {
t.Errorf("standLiveInfo 三要素映射错误: %+v", standLive)
}
if standLive["inTime"] != "24" {
t.Errorf("inTime = %v, want 24", standLive["inTime"])
}
security := report["securityInfo"].(map[string]interface{})
if security["front"] != 1 || security["escape"] != 0 || security["drug"] != 1 {
t.Errorf("securityInfo 解析错误: %+v", security)
}
antiFraud := report["antiFraudInfo"].(map[string]interface{})
if antiFraud["gamblerBanker"] != "A" {
t.Errorf("antiFraudInfo.gamblerBanker = %v", antiFraud["gamblerBanker"])
}
riskList := report["riskList"].(map[string]interface{})
if riskList["creditLeaseRisk"] != 1 {
t.Errorf("creditLeaseRisk = %v, want 1", riskList["creditLeaseRisk"])
}
if riskList["vehicleLeaseViolation"] != 1 {
t.Errorf("vehicleLeaseViolation = %v, want 1", riskList["vehicleLeaseViolation"])
}
if riskList["highRiskArea"] != 0 {
t.Errorf("highRiskArea = %v, want 0", riskList["highRiskArea"])
}
riskPoint := report["riskPoint"].(map[string]interface{})
if riskPoint["antiFraudRisk"] != 1 {
t.Errorf("antiFraudRisk = %v, want 1", riskPoint["antiFraudRisk"])
}
if riskPoint["judicialCase"] != 0 {
t.Errorf("judicialCase = %v, want 0", riskPoint["judicialCase"])
}
perf := report["performanceStatistics"].(map[string]interface{})
if perf["serialVersionUID"] != 1 {
t.Errorf("serialVersionUID = %v, want 1", perf["serialVersionUID"])
}
}
func TestMapYYSYH6F3StandLive(t *testing.T) {
cases := []struct {
result, wantFinal, wantVerify string
}{
{"0", "0", "0"},
{"1", "1", "1"},
{"2", "1", "-1"},
{"", "1", "-1"},
}
for _, tc := range cases {
final, verify := mapYYSYH6F3StandLive(tc.result)
if final != tc.wantFinal || verify != tc.wantVerify {
t.Errorf("result=%q got (%s,%s) want (%s,%s)", tc.result, final, verify, tc.wantFinal, tc.wantVerify)
}
}
}
func TestParseSecurityInfoLevel(t *testing.T) {
info := parseSecurityInfoLevel("A,C3")
if info["escape"] != 1 || info["front"] != 0 || info["drug"] != 1 {
t.Fatalf("A,C3 => %+v", info)
}
info = parseSecurityInfoLevel("A1")
if info["front"] != 1 || info["escape"] != 0 {
t.Fatalf("A1 => %+v", info)
}
}
func TestIndustryBlacklistHit(t *testing.T) {
if !industryBlacklistHit("D1,B") {
t.Fatal("D1 should hit industry blacklist")
}
if industryBlacklistHit("A1,C3") {
t.Fatal("A1,C3 should not hit industry blacklist")
}
}
func TestReportNoNullValues(t *testing.T) {
params := dto.DWBG6A2CReq{
Name: "张三",
IDCard: "320321199102011152",
MobileNo: "13812345678",
}
apiData := map[string]interface{}{
"FLXG7E8F": map[string]interface{}{
"judicial_data": map[string]interface{}{
"breachCaseList": []interface{}{},
"consumptionRestrictionList": []interface{}{},
"lawsuitStat": map[string]interface{}{
"count": map[string]interface{}{
"count_beigao": 0,
"larq_stat": "",
},
"civil": map[string]interface{}{
"cases": []interface{}{},
"count": map[string]interface{}{"count_total": 0},
},
},
},
},
}
report := transformToSinanReport(apiData, params, zap.NewNop())
cleaned, ok := stripNullValues(report).(map[string]interface{})
if !ok {
t.Fatal("stripNullValues failed")
}
if reportContainsNull(cleaned) {
t.Fatal("report still contains null after strip")
}
data, err := json.Marshal(cleaned)
if err != nil {
t.Fatalf("marshal failed: %v", err)
}
if strings.Contains(string(data), "null") {
t.Fatalf("JSON contains null: %s", string(data))
}
}
func TestBuildJudicialLeaseReportWithCases(t *testing.T) {
apiData := map[string]interface{}{
"FLXG7E8F": map[string]interface{}{
"judicial_data": map[string]interface{}{
"breachCaseList": []interface{}{},
"consumptionRestrictionList": []interface{}{},
"lawsuitStat": map[string]interface{}{
"count": map[string]interface{}{
"count_total": 1,
"count_beigao": 1,
"larq_stat": "2026(1)",
"ay_stat": "民事(1)",
},
"civil": map[string]interface{}{
"cases": []interface{}{
map[string]interface{}{
"c_ah": "2019桂0103民初5129号",
"n_ssdw": "原告",
"n_ajjzjd": "已结案",
"n_ajlx": "民事一审",
"c_dsrxx": []interface{}{
map[string]interface{}{
"c_mc": "黄春丽",
"n_ssdw": "原告",
"n_dsrlx": "自然人",
},
},
},
},
"count": map[string]interface{}{
"count_total": 1,
"count_beigao": 1,
},
},
"preservation": map[string]interface{}{
"cases": []interface{}{},
"count": map[string]interface{}{"count_total": 1},
},
"implement": map[string]interface{}{
"cases": []interface{}{},
"count": map[string]interface{}{"count_total": 0},
},
},
},
},
}
jlr := buildJudicialLeaseReport(apiData)
courtInfo := jlr["courtInfo"].(map[string]interface{})
if courtInfo["civilCasesCount"] != 1 {
t.Fatalf("civilCasesCount = %v", courtInfo["civilCasesCount"])
}
if courtInfo["preservationCasesCount"] != 1 {
t.Fatalf("preservationCasesCount = %v", courtInfo["preservationCasesCount"])
}
newMult := courtInfo["newMultCourtInfo"].(map[string]interface{})
civilCases, ok := newMult["civilCases"].([]interface{})
if !ok || len(civilCases) != 1 {
t.Fatalf("civilCases missing or empty: %+v", newMult["civilCases"])
}
if _, has := newMult["preservationCases"]; has {
t.Fatal("preservationCases list should be omitted when empty")
}
overview := jlr["caseOverviewInfo"].(map[string]interface{})
if overview["beigaoTotalCasesCounts"] != 1 {
t.Fatalf("beigaoTotalCasesCounts = %v", overview["beigaoTotalCasesCounts"])
}
}
func TestM1PlusCountCaps(t *testing.T) {
apiData := map[string]interface{}{
"JRZQ5E9F": map[string]interface{}{
"xyp_cpl0029": "1",
"xyp_cpl0030": "1",
"xyp_cpl0031": "1",
},
}
record := buildOverdueRecord(apiData)
if record["m1PlusCountLast6Months"] != 3 {
t.Fatalf("6m cap = %v", record["m1PlusCountLast6Months"])
}
if record["m1PlusCountLast12Months"] != 3 {
t.Fatalf("12m cap = %v", record["m1PlusCountLast12Months"])
}
}