topfans/backend/services/assetService/repository/asset_repository_test.go
2026-04-07 22:29:48 +08:00

430 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/topfans/backend/pkg/database"
"github.com/topfans/backend/pkg/models"
"gorm.io/gorm"
)
// setupTestDB 设置测试数据库
func setupTestDB(t *testing.T) *gorm.DB {
config := database.Config{
Host: "localhost",
Port: 5432,
User: "haihuizhu",
Password: "admin",
DBName: "top-fans",
SSLMode: "disable",
TimeZone: "Asia/Shanghai",
}
if err := database.Init(config); err != nil {
t.Skipf("Skipping test: failed to connect to test database: %v", err)
}
db := database.GetDB()
// 迁移资产相关表
if err := db.AutoMigrate(&models.Asset{}, &models.MintOrder{}, &models.AssetLike{}); err != nil {
t.Logf("Warning: Failed to migrate asset tables (may already exist): %v", err)
}
// 测试开始前先清理一次,确保测试环境干净
cleanupTestDB(t, db)
return db
}
// cleanupTestDB 清理测试数据
func cleanupTestDB(t *testing.T, db *gorm.DB) {
// 清理测试数据(注意外键约束顺序)
// 先清理关联表
db.Exec("DELETE FROM asset_likes WHERE user_id IN (SELECT id FROM users WHERE mobile LIKE '199%') OR asset_id IN (SELECT id FROM assets WHERE owner_uid IN (SELECT id FROM users WHERE mobile LIKE '199%'))")
db.Exec("DELETE FROM assets WHERE owner_uid IN (SELECT id FROM users WHERE mobile LIKE '199%')")
db.Exec("DELETE FROM mint_orders WHERE user_id IN (SELECT id FROM users WHERE mobile LIKE '199%')")
db.Exec("DELETE FROM fan_profiles WHERE user_id IN (SELECT id FROM users WHERE mobile LIKE '199%')")
db.Exec("DELETE FROM users WHERE mobile LIKE '199%'")
// 清理测试明星(包括 test_asset_% 和 test_mint_%
db.Exec("DELETE FROM stars WHERE identity_id LIKE 'test_asset_%' OR identity_id LIKE 'test_mint_%'")
}
// createTestStar 创建测试用明星
func createTestStar(t *testing.T, db *gorm.DB, identityID string) *models.Star {
// 先检查是否已存在
var existingStar models.Star
if err := db.Where("identity_id = ?", identityID).First(&existingStar).Error; err == nil {
// 已存在,返回现有的
return &existingStar
}
// 不存在,创建新的
star := &models.Star{
Name: "测试明星-" + identityID,
IdentityID: identityID,
IsActive: true,
}
if err := db.Create(star).Error; err != nil {
t.Fatalf("Failed to create test star: %v", err)
}
return star
}
// createTestUser 创建测试用户
func createTestUser(t *testing.T, db *gorm.DB, mobile string) *models.User {
user := &models.User{
Mobile: mobile,
PasswordHash: "test_hash",
IsActive: true,
}
if err := db.Create(user).Error; err != nil {
t.Fatalf("Failed to create test user: %v", err)
}
return user
}
// createTestFanProfile 创建测试粉丝档案
func createTestFanProfile(t *testing.T, db *gorm.DB, userID, starID int64, nickname string) *models.FanProfile {
profile := &models.FanProfile{
UserID: userID,
StarID: starID,
Nickname: nickname,
Level: 1,
}
if err := db.Create(profile).Error; err != nil {
t.Fatalf("Failed to create test fan profile: %v", err)
}
return profile
}
// createTestAsset 创建测试资产
func createTestAsset(t *testing.T, db *gorm.DB, ownerUID, starID int64, name string) *models.Asset {
asset := &models.Asset{
OwnerUID: ownerUID,
StarID: starID,
Name: name,
CoverURL: "https://example.com/cover.jpg",
Status: models.AssetStatusPending,
}
if err := db.Create(asset).Error; err != nil {
t.Fatalf("Failed to create test asset: %v", err)
}
return asset
}
// TestAssetRepository_Create 测试创建资产
func TestAssetRepository_Create(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_create")
user := createTestUser(t, db, "19900000001")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
// 测试创建资产
asset := &models.Asset{
OwnerUID: user.ID,
StarID: star.StarID,
Name: "测试资产",
CoverURL: "https://example.com/cover.jpg",
Status: models.AssetStatusPending,
}
err := repo.Create(asset)
assert.NoError(t, err)
assert.NotZero(t, asset.ID)
assert.NotZero(t, asset.CreatedAt)
assert.NotZero(t, asset.UpdatedAt)
}
// TestAssetRepository_GetByID 测试根据ID查询资产
func TestAssetRepository_GetByID(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_getbyid")
user := createTestUser(t, db, "19900000002")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 测试查询存在的资产
result, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.NotNil(t, result)
assert.Equal(t, asset.ID, result.ID)
assert.Equal(t, asset.Name, result.Name)
// 测试查询不存在的资产
result, err = repo.GetByID(999999)
assert.Error(t, err)
assert.Nil(t, result)
}
// TestAssetRepository_GetByIDAndOwner 测试根据ID和所有者查询资产
func TestAssetRepository_GetByIDAndOwner(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_owner")
user1 := createTestUser(t, db, "19900000003")
user2 := createTestUser(t, db, "19900000004")
createTestFanProfile(t, db, user1.ID, star.StarID, "用户1")
createTestFanProfile(t, db, user2.ID, star.StarID, "用户2")
asset := createTestAsset(t, db, user1.ID, star.StarID, "用户1的资产")
// 测试正确的所有者
result, err := repo.GetByIDAndOwner(asset.ID, user1.ID, star.StarID)
assert.NoError(t, err)
assert.NotNil(t, result)
assert.Equal(t, asset.ID, result.ID)
// 测试错误的所有者
result, err = repo.GetByIDAndOwner(asset.ID, user2.ID, star.StarID)
assert.Error(t, err)
assert.Nil(t, result)
// 测试错误的 StarID
result, err = repo.GetByIDAndOwner(asset.ID, user1.ID, 999999)
assert.Error(t, err)
assert.Nil(t, result)
}
// TestAssetRepository_GetByOwner 测试查询用户的资产列表
func TestAssetRepository_GetByOwner(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_list")
user := createTestUser(t, db, "19900000005")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
// 创建多个资产
for i := 1; i <= 5; i++ {
createTestAsset(t, db, user.ID, star.StarID, "资产"+string(rune('0'+i)))
time.Sleep(10 * time.Millisecond) // 确保创建时间不同
}
// 测试查询列表(分页)
assets, err := repo.GetByOwner(user.ID, star.StarID, 3, 0)
assert.NoError(t, err)
assert.Len(t, assets, 3)
// 测试第二页
assets, err = repo.GetByOwner(user.ID, star.StarID, 3, 3)
assert.NoError(t, err)
assert.Len(t, assets, 2)
// 验证按创建时间倒序排列
allAssets, err := repo.GetByOwner(user.ID, star.StarID, 10, 0)
assert.NoError(t, err)
assert.Len(t, allAssets, 5)
for i := 0; i < len(allAssets)-1; i++ {
assert.GreaterOrEqual(t, allAssets[i].CreatedAt, allAssets[i+1].CreatedAt)
}
}
// TestAssetRepository_CountByOwner 测试统计用户的资产数量
func TestAssetRepository_CountByOwner(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_count")
user := createTestUser(t, db, "19900000006")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
// 初始数量应该为0
count, err := repo.CountByOwner(user.ID, star.StarID)
assert.NoError(t, err)
assert.Equal(t, int64(0), count)
// 创建3个资产
for i := 0; i < 3; i++ {
createTestAsset(t, db, user.ID, star.StarID, "资产")
}
// 验证数量
count, err = repo.CountByOwner(user.ID, star.StarID)
assert.NoError(t, err)
assert.Equal(t, int64(3), count)
}
// TestAssetRepository_UpdateStatus 测试更新资产状态
func TestAssetRepository_UpdateStatus(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_status")
user := createTestUser(t, db, "19900000007")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 验证初始状态
assert.Equal(t, int32(models.AssetStatusPending), asset.Status)
// 更新状态
err := repo.UpdateStatus(asset.ID, models.AssetStatusActive)
assert.NoError(t, err)
// 验证状态已更新
updated, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(models.AssetStatusActive), updated.Status)
}
// TestAssetRepository_UpdateBlockchainInfo 测试更新上链信息
func TestAssetRepository_UpdateBlockchainInfo(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_mint")
user := createTestUser(t, db, "19900000008")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 更新上链信息
txHash := "0x1234567890abcdef"
blockNumber := int64(12345)
mintedAt := time.Now().UnixMilli()
err := repo.UpdateBlockchainInfo(asset.ID, txHash, blockNumber, mintedAt)
assert.NoError(t, err)
// 验证信息已更新
updated, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.NotNil(t, updated.TxHash)
assert.Equal(t, txHash, *updated.TxHash)
assert.NotNil(t, updated.BlockNumber)
assert.Equal(t, blockNumber, *updated.BlockNumber)
assert.NotNil(t, updated.MintedAt)
assert.Equal(t, mintedAt, *updated.MintedAt)
}
// TestAssetRepository_IncrementLikeCount 测试原子增加点赞数
func TestAssetRepository_IncrementLikeCount(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_like")
user := createTestUser(t, db, "19900000009")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 验证初始点赞数
assert.Equal(t, int32(0), asset.LikeCount)
// 增加点赞数
err := repo.IncrementLikeCount(asset.ID)
assert.NoError(t, err)
// 验证点赞数已增加
updated, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(1), updated.LikeCount)
// 再次增加
err = repo.IncrementLikeCount(asset.ID)
assert.NoError(t, err)
updated, err = repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(2), updated.LikeCount)
}
// TestAssetRepository_DecrementLikeCount 测试原子减少点赞数
func TestAssetRepository_DecrementLikeCount(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_unlike")
user := createTestUser(t, db, "19900000010")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 先增加点赞数到3
db.Model(&models.Asset{}).Where("id = ?", asset.ID).Update("like_count", 3)
// 减少点赞数
err := repo.DecrementLikeCount(asset.ID)
assert.NoError(t, err)
// 验证点赞数已减少
updated, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(2), updated.LikeCount)
// 测试不会减到负数
db.Model(&models.Asset{}).Where("id = ?", asset.ID).Update("like_count", 0)
err = repo.DecrementLikeCount(asset.ID)
assert.NoError(t, err)
updated, err = repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(0), updated.LikeCount) // 不应该变成负数
}
// TestAssetRepository_LikeCount 测试点赞数功能
func TestAssetRepository_LikeCount(t *testing.T) {
db := setupTestDB(t)
defer cleanupTestDB(t, db)
repo := NewAssetRepository(db)
// 创建测试数据
star := createTestStar(t, db, "test_asset_likecount")
user := createTestUser(t, db, "19900000011")
createTestFanProfile(t, db, user.ID, star.StarID, "测试用户")
asset := createTestAsset(t, db, user.ID, star.StarID, "测试资产")
// 验证初始点赞数为0
result, err := repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(0), result.LikeCount)
// 增加点赞数
err = repo.IncrementLikeCount(asset.ID)
assert.NoError(t, err)
result, err = repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(1), result.LikeCount)
// 减少点赞数
err = repo.DecrementLikeCount(asset.ID)
assert.NoError(t, err)
result, err = repo.GetByID(asset.ID)
assert.NoError(t, err)
assert.Equal(t, int32(0), result.LikeCount)
}