430 lines
13 KiB
Go
430 lines
13 KiB
Go
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)
|
||
}
|