feat: add kyc test
This commit is contained in:
parent
bf8d532c6e
commit
14678b986b
|
@ -97,11 +97,23 @@ func (repo *KYCRepository) List(ctx context.Context, params repository.KYCQueryP
|
|||
sort = append(sort, bson.E{Key: "created_at", Value: -1})
|
||||
}
|
||||
|
||||
var results []*entity.KYC
|
||||
total, err := repo.DB.GetClient().FindManyWithTotal(ctx, &results, filter, params.PageIndex, params.PageSize, WithSort(sort))
|
||||
// 設置排序選項
|
||||
opts := options.Find().SetSkip((params.PageIndex - 1) * params.PageSize).SetLimit(params.PageSize)
|
||||
opts.SetSort(bson.D{{Key: "updated_at", Value: -1}})
|
||||
|
||||
// 查詢符合條件的總數
|
||||
total, err := repo.DB.GetClient().CountDocuments(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 執行查詢並獲取結果
|
||||
var results []*entity.KYC
|
||||
err = repo.DB.GetClient().Find(ctx, &results, filter, opts)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return results, total, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,477 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/entity"
|
||||
"code.30cm.net/digimon/app-cloudep-product-service/pkg/domain/repository"
|
||||
mgo "code.30cm.net/digimon/library-go/mongo"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/mon"
|
||||
"github.com/zeromicro/go-zero/core/stores/redis"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SetupTestKYCRepository(db string) (repository.KYCRepository, func(), error) {
|
||||
h, p, tearDown, err := startMongoContainer()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
s, _ := miniredis.Run()
|
||||
|
||||
conf := &mgo.Conf{
|
||||
Schema: Schema,
|
||||
Host: fmt.Sprintf("%s:%s", h, p),
|
||||
Database: db,
|
||||
MaxStaleness: 300,
|
||||
MaxPoolSize: 100,
|
||||
MinPoolSize: 100,
|
||||
MaxConnIdleTime: 300,
|
||||
Compressors: []string{},
|
||||
EnableStandardReadWriteSplitMode: false,
|
||||
ConnectTimeoutMs: 3000,
|
||||
}
|
||||
|
||||
cacheConf := cache.CacheConf{
|
||||
cache.NodeConf{
|
||||
RedisConf: redis.RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: redis.NodeType,
|
||||
},
|
||||
Weight: 100,
|
||||
},
|
||||
}
|
||||
|
||||
cacheOpts := []cache.Option{
|
||||
cache.WithExpiry(1000 * time.Microsecond),
|
||||
cache.WithNotFoundExpiry(1000 * time.Microsecond),
|
||||
}
|
||||
|
||||
param := KYCRepositoryParam{
|
||||
Conf: conf,
|
||||
CacheConf: cacheConf,
|
||||
CacheOpts: cacheOpts,
|
||||
DBOpts: []mon.Option{
|
||||
mgo.SetCustomDecimalType(),
|
||||
mgo.InitMongoOptions(*conf),
|
||||
},
|
||||
}
|
||||
|
||||
repo := NewKYCRepository(param)
|
||||
//_, _ = repo.Index20250317001UP(context.Background())
|
||||
|
||||
return repo, tearDown, nil
|
||||
}
|
||||
|
||||
func TestInsertKYC(t *testing.T) {
|
||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
||||
assert.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 建立多筆 KYC 資料
|
||||
items := []entity.KYC{
|
||||
{
|
||||
UID: "user-a",
|
||||
CountryRegion: "TW",
|
||||
Name: "王小明",
|
||||
Identification: "A123456789",
|
||||
IdentificationType: "ID_CARD",
|
||||
Address: "台北市信義區",
|
||||
PostalCode: "110",
|
||||
Status: "PENDING",
|
||||
},
|
||||
{
|
||||
UID: "user-b",
|
||||
CountryRegion: "US",
|
||||
Name: "John Smith",
|
||||
Identification: "P987654321",
|
||||
IdentificationType: "PASSPORT",
|
||||
Address: "123 Main St, NY",
|
||||
PostalCode: "10001",
|
||||
Status: "PENDING",
|
||||
},
|
||||
}
|
||||
|
||||
// 插入資料
|
||||
for i := range items {
|
||||
err := model.Create(ctx, &items[i])
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, items[i].ID.IsZero(), "ID 應自動產生")
|
||||
assert.NotZero(t, items[i].CreatedAt)
|
||||
assert.NotZero(t, items[i].UpdatedAt)
|
||||
}
|
||||
|
||||
// 驗證插入資料是否正確
|
||||
for _, item := range items {
|
||||
kyc, err := model.FindByID(ctx, item.ID.Hex())
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, item.UID, kyc.UID)
|
||||
assert.Equal(t, item.Name, kyc.Name)
|
||||
assert.Equal(t, item.CountryRegion, kyc.CountryRegion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindLatestByUID(t *testing.T) {
|
||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
||||
assert.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
ctx := context.Background()
|
||||
now := time.Now().UnixNano()
|
||||
|
||||
// 測試資料準備
|
||||
testData := []entity.KYC{
|
||||
{
|
||||
UID: "user-multi",
|
||||
Name: "早期資料",
|
||||
Status: "PENDING",
|
||||
CreatedAt: now - 1000,
|
||||
UpdatedAt: now - 1000,
|
||||
},
|
||||
{
|
||||
UID: "user-multi",
|
||||
Name: "最新資料",
|
||||
Status: "APPROVED",
|
||||
CreatedAt: now + 1000,
|
||||
UpdatedAt: now + 1000,
|
||||
},
|
||||
{
|
||||
UID: "user-single",
|
||||
Name: "唯一資料",
|
||||
Status: "PENDING",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range testData {
|
||||
err := model.Create(ctx, &testData[i])
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// table-driven 測試表
|
||||
tests := []struct {
|
||||
name string
|
||||
uid string
|
||||
expectNil bool
|
||||
expect string // 預期的 Name
|
||||
}{
|
||||
{
|
||||
name: "多筆資料,取最新",
|
||||
uid: "user-multi",
|
||||
expectNil: false,
|
||||
expect: "最新資料",
|
||||
},
|
||||
{
|
||||
name: "單筆資料",
|
||||
uid: "user-single",
|
||||
expectNil: false,
|
||||
expect: "唯一資料",
|
||||
},
|
||||
{
|
||||
name: "查無資料",
|
||||
uid: "user-none",
|
||||
expectNil: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result, err := model.FindLatestByUID(ctx, tt.uid)
|
||||
if tt.expectNil {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, result)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, tt.expect, result.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKYCRepository_List(t *testing.T) {
|
||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
||||
assert.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
ctx := context.Background()
|
||||
now := time.Now().UnixNano()
|
||||
|
||||
seedData := []entity.KYC{
|
||||
{
|
||||
UID: "user-1",
|
||||
CountryRegion: "TW",
|
||||
Status: "PENDING",
|
||||
Name: "Alice",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
},
|
||||
{
|
||||
UID: "user-1",
|
||||
CountryRegion: "JP",
|
||||
Status: "APPROVED",
|
||||
Name: "Bob",
|
||||
CreatedAt: now + 1,
|
||||
UpdatedAt: now + 1,
|
||||
},
|
||||
{
|
||||
UID: "user-2",
|
||||
CountryRegion: "US",
|
||||
Status: "REJECTED",
|
||||
Name: "Charlie",
|
||||
CreatedAt: now + 2,
|
||||
UpdatedAt: now + 2,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range seedData {
|
||||
err := model.Create(ctx, &seedData[i])
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
params repository.KYCQueryParams
|
||||
expectedCount int
|
||||
expectedTotal int64
|
||||
expectedFirst string
|
||||
}{
|
||||
{
|
||||
name: "Query by UID",
|
||||
params: repository.KYCQueryParams{
|
||||
UID: ptr("user-1"),
|
||||
PageSize: 10,
|
||||
PageIndex: 1,
|
||||
},
|
||||
expectedCount: 2,
|
||||
expectedTotal: 2,
|
||||
},
|
||||
{
|
||||
name: "Query by CountryRegion",
|
||||
params: repository.KYCQueryParams{
|
||||
Country: ptr("JP"),
|
||||
PageSize: 10,
|
||||
PageIndex: 1,
|
||||
},
|
||||
expectedCount: 1,
|
||||
expectedTotal: 1,
|
||||
expectedFirst: "Bob",
|
||||
},
|
||||
{
|
||||
name: "Query by Status",
|
||||
params: repository.KYCQueryParams{
|
||||
Status: ptr("REJECTED"),
|
||||
PageSize: 10,
|
||||
PageIndex: 1,
|
||||
},
|
||||
expectedCount: 1,
|
||||
expectedTotal: 1,
|
||||
expectedFirst: "Charlie",
|
||||
},
|
||||
{
|
||||
name: "Pagination test",
|
||||
params: repository.KYCQueryParams{
|
||||
PageSize: 1,
|
||||
PageIndex: 1,
|
||||
},
|
||||
expectedCount: 1,
|
||||
expectedTotal: 3,
|
||||
},
|
||||
{
|
||||
name: "No match",
|
||||
params: repository.KYCQueryParams{
|
||||
UID: ptr("non-existent"),
|
||||
PageSize: 10,
|
||||
PageIndex: 1,
|
||||
},
|
||||
expectedCount: 0,
|
||||
expectedTotal: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
list, total, err := model.List(ctx, tt.params)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expectedCount, len(list))
|
||||
assert.Equal(t, tt.expectedTotal, total)
|
||||
if tt.expectedFirst != "" && len(list) > 0 {
|
||||
assert.Equal(t, tt.expectedFirst, list[0].Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKYCRepository_UpdateStatus(t *testing.T) {
|
||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
||||
assert.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 建立一筆 KYC 資料
|
||||
kyc := &entity.KYC{
|
||||
UID: "user-status",
|
||||
Name: "測試用戶",
|
||||
Status: "PENDING",
|
||||
CreatedAt: time.Now().UnixNano(),
|
||||
UpdatedAt: time.Now().UnixNano(),
|
||||
}
|
||||
err = model.Create(ctx, kyc)
|
||||
assert.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
newStatus string
|
||||
reason string
|
||||
expectErr bool
|
||||
expectStatus string
|
||||
}{
|
||||
{
|
||||
name: "成功更新為 REJECTED",
|
||||
id: kyc.ID.Hex(),
|
||||
newStatus: "REJECTED",
|
||||
reason: "文件不符",
|
||||
expectErr: false,
|
||||
expectStatus: "REJECTED",
|
||||
},
|
||||
{
|
||||
name: "失敗 - 無效 ID 格式",
|
||||
id: "not-a-valid-id",
|
||||
newStatus: "APPROVED",
|
||||
reason: "",
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "失敗 - 找不到資料",
|
||||
id: primitive.NewObjectID().Hex(), // 合法但不存在
|
||||
newStatus: "APPROVED",
|
||||
reason: "",
|
||||
expectErr: false, // Mongo 不會報錯,但更新筆數是 0,後面可以補強這邊驗證
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := model.UpdateStatus(ctx, tt.id, tt.newStatus, tt.reason)
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 如果是第一個 case,檢查資料是否真的被更新
|
||||
if tt.expectStatus != "" {
|
||||
result, err := model.FindByID(ctx, tt.id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.expectStatus, result.Status)
|
||||
assert.Equal(t, tt.reason, result.RejectReason)
|
||||
assert.NotZero(t, result.UpdatedAt)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKYCRepository_UpdateKYCInfo(t *testing.T) {
|
||||
model, tearDown, err := SetupTestKYCRepository("testDB")
|
||||
assert.NoError(t, err)
|
||||
defer tearDown()
|
||||
|
||||
ctx := context.Background()
|
||||
now := time.Now().UnixNano()
|
||||
|
||||
// 建立兩筆資料:一筆 PENDING、一筆 APPROVED
|
||||
pendingKYC := &entity.KYC{
|
||||
UID: "user-pending",
|
||||
Name: "原名",
|
||||
Address: "原地址",
|
||||
Status: "PENDING",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
err = model.Create(ctx, pendingKYC)
|
||||
assert.NoError(t, err)
|
||||
|
||||
approvedKYC := &entity.KYC{
|
||||
UID: "user-approved",
|
||||
Name: "原名",
|
||||
Address: "原地址",
|
||||
Status: "APPROVED",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
err = model.Create(ctx, approvedKYC)
|
||||
assert.NoError(t, err)
|
||||
|
||||
name := "新名字"
|
||||
address := "新地址"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
id string
|
||||
update *repository.KYCUpdateParams
|
||||
expectErr bool
|
||||
expectApply bool // 預期更新是否應成功套用
|
||||
}{
|
||||
{
|
||||
name: "成功更新 PENDING 狀態資料",
|
||||
id: pendingKYC.ID.Hex(),
|
||||
update: &repository.KYCUpdateParams{
|
||||
Name: &name,
|
||||
Address: &address,
|
||||
},
|
||||
expectErr: false,
|
||||
expectApply: true,
|
||||
},
|
||||
{
|
||||
name: "更新失敗 - 非 PENDING 狀態",
|
||||
id: approvedKYC.ID.Hex(),
|
||||
update: &repository.KYCUpdateParams{
|
||||
Name: &name,
|
||||
Address: &address,
|
||||
},
|
||||
expectErr: false,
|
||||
expectApply: false,
|
||||
},
|
||||
{
|
||||
name: "更新失敗 - 非法 ID 格式",
|
||||
id: "not-an-id",
|
||||
update: &repository.KYCUpdateParams{
|
||||
Name: &name,
|
||||
},
|
||||
expectErr: true,
|
||||
expectApply: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := model.UpdateKYCInfo(ctx, tt.id, tt.update)
|
||||
if tt.expectErr {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 若預期資料已被套用,驗證欄位是否更新
|
||||
if tt.expectApply {
|
||||
got, err := model.FindByID(ctx, tt.id)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, name, got.Name)
|
||||
assert.Equal(t, address, got.Address)
|
||||
} else {
|
||||
got, err := model.FindByID(ctx, tt.id)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEqual(t, name, got.Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue