HaniBlindBox/server/HoneyBox/tests/HoneyBox.Tests/Services/DesignatedPrizeServiceTests.cs
2026-02-01 19:30:51 +08:00

493 lines
14 KiB
C#

using HoneyBox.Admin.Business.Models;
using HoneyBox.Admin.Business.Models.DesignatedPrize;
using HoneyBox.Admin.Business.Services;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Moq;
using Xunit;
namespace HoneyBox.Tests.Services;
/// <summary>
/// DesignatedPrizeService 单元测试
/// </summary>
public class DesignatedPrizeServiceTests : IDisposable
{
private readonly HoneyBoxDbContext _dbContext;
private readonly Mock<ILogger<DesignatedPrizeService>> _mockLogger;
private readonly DesignatedPrizeService _service;
public DesignatedPrizeServiceTests()
{
var options = new DbContextOptionsBuilder<HoneyBoxDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_dbContext = new HoneyBoxDbContext(options);
_mockLogger = new Mock<ILogger<DesignatedPrizeService>>();
_service = new DesignatedPrizeService(_dbContext, _mockLogger.Object);
}
public void Dispose()
{
_dbContext.Dispose();
}
#region GetByGoodsIdAsync Tests
[Fact]
public async Task GetByGoodsIdAsync_WithExistingGoods_ReturnsConfigs()
{
// Arrange
await SeedTestDataAsync();
var goods = await _dbContext.Goods.FirstAsync();
// Act
var result = await _service.GetByGoodsIdAsync(goods.Id);
// Assert
Assert.NotNull(result);
Assert.Single(result);
}
[Fact]
public async Task GetByGoodsIdAsync_WithNonExistingGoods_ThrowsException()
{
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.GetByGoodsIdAsync(99999));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("盒子不存在", exception.Message);
}
[Fact]
public async Task GetByGoodsIdAsync_WithDeletedGoods_ThrowsException()
{
// Arrange
var deletedGoods = new Good
{
Title = "已删除商品",
ImgUrl = "http://test.com/deleted.jpg",
ImgUrlDetail = "http://test.com/deleted_detail.jpg",
Price = 10,
Type = 1,
Status = 1,
Stock = 10,
DeletedAt = DateTime.Now,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Goods.Add(deletedGoods);
await _dbContext.SaveChangesAsync();
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.GetByGoodsIdAsync(deletedGoods.Id));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
}
[Fact]
public async Task GetByGoodsIdAsync_ReturnsConfigsWithUserAndPrizeInfo()
{
// Arrange
await SeedTestDataAsync();
var goods = await _dbContext.Goods.FirstAsync();
// Act
var result = await _service.GetByGoodsIdAsync(goods.Id);
// Assert
Assert.NotNull(result);
var config = result.First();
Assert.NotNull(config.GoodsItemTitle);
Assert.NotNull(config.UserNickname);
}
#endregion
#region CreateAsync Tests
[Fact]
public async Task CreateAsync_WithValidRequest_CreatesConfig()
{
// Arrange
await SeedGoodsWithPrizesAndUsersAsync();
var goods = await _dbContext.Goods.FirstAsync();
var prize = await _dbContext.GoodsItems.FirstAsync(gi => gi.GoodsId == goods.Id);
var user = await _dbContext.Users.FirstAsync();
var request = new CreateDesignatedPrizeRequest
{
GoodsItemId = prize.Id,
UserId = user.Id,
Remark = "测试备注"
};
// Act
var result = await _service.CreateAsync(goods.Id, request);
// Assert
Assert.NotNull(result);
Assert.Equal(goods.Id, result.GoodsId);
Assert.Equal(prize.Id, result.GoodsItemId);
Assert.Equal(user.Id, result.UserId);
Assert.True(result.IsActive);
Assert.Equal("测试备注", result.Remark);
}
[Fact]
public async Task CreateAsync_WithNonExistingGoods_ThrowsException()
{
// Arrange
var request = new CreateDesignatedPrizeRequest
{
GoodsItemId = 1,
UserId = 1
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.CreateAsync(99999, request));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("盒子不存在", exception.Message);
}
[Fact]
public async Task CreateAsync_WithNonExistingPrize_ThrowsException()
{
// Arrange
await SeedGoodsWithPrizesAndUsersAsync();
var goods = await _dbContext.Goods.FirstAsync();
var user = await _dbContext.Users.FirstAsync();
var request = new CreateDesignatedPrizeRequest
{
GoodsItemId = 99999,
UserId = user.Id
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.CreateAsync(goods.Id, request));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("奖品不存在", exception.Message);
}
[Fact]
public async Task CreateAsync_WithNonExistingUser_ThrowsException()
{
// Arrange
await SeedGoodsWithPrizesAndUsersAsync();
var goods = await _dbContext.Goods.FirstAsync();
var prize = await _dbContext.GoodsItems.FirstAsync(gi => gi.GoodsId == goods.Id);
var request = new CreateDesignatedPrizeRequest
{
GoodsItemId = prize.Id,
UserId = 99999
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.CreateAsync(goods.Id, request));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("用户不存在", exception.Message);
}
[Fact]
public async Task CreateAsync_WithDuplicateConfig_ThrowsException()
{
// Arrange
await SeedTestDataAsync();
var existingConfig = await _dbContext.GoodsDesignatedPrizes.FirstAsync();
var user = await _dbContext.Users.FirstAsync();
var request = new CreateDesignatedPrizeRequest
{
GoodsItemId = existingConfig.GoodsItemId,
UserId = user.Id
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.CreateAsync(existingConfig.GoodsId, request));
Assert.Equal(BusinessErrorCodes.Conflict, exception.Code);
Assert.Contains("该奖品已配置指定用户", exception.Message);
}
#endregion
#region UpdateAsync Tests
[Fact]
public async Task UpdateAsync_WithValidRequest_UpdatesConfig()
{
// Arrange
await SeedTestDataAsync();
var config = await _dbContext.GoodsDesignatedPrizes.FirstAsync();
var request = new UpdateDesignatedPrizeRequest
{
IsActive = false,
Remark = "更新后的备注"
};
// Act
var result = await _service.UpdateAsync(config.Id, request);
// Assert
Assert.NotNull(result);
Assert.False(result.IsActive);
Assert.Equal("更新后的备注", result.Remark);
}
[Fact]
public async Task UpdateAsync_WithNewUserId_UpdatesUser()
{
// Arrange
await SeedTestDataAsync();
var config = await _dbContext.GoodsDesignatedPrizes.FirstAsync();
// Add another user
var newUser = new User
{
OpenId = "new_openid",
Uid = "new_uid",
Nickname = "新用户",
HeadImg = "http://test.com/new.jpg",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Users.Add(newUser);
await _dbContext.SaveChangesAsync();
var request = new UpdateDesignatedPrizeRequest
{
UserId = newUser.Id
};
// Act
var result = await _service.UpdateAsync(config.Id, request);
// Assert
Assert.NotNull(result);
Assert.Equal(newUser.Id, result.UserId);
}
[Fact]
public async Task UpdateAsync_WithNonExistingConfig_ThrowsException()
{
// Arrange
var request = new UpdateDesignatedPrizeRequest
{
IsActive = false
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.UpdateAsync(99999, request));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("配置不存在", exception.Message);
}
[Fact]
public async Task UpdateAsync_WithNonExistingNewUser_ThrowsException()
{
// Arrange
await SeedTestDataAsync();
var config = await _dbContext.GoodsDesignatedPrizes.FirstAsync();
var request = new UpdateDesignatedPrizeRequest
{
UserId = 99999
};
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.UpdateAsync(config.Id, request));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("用户不存在", exception.Message);
}
#endregion
#region DeleteAsync Tests
[Fact]
public async Task DeleteAsync_WithExistingConfig_DeletesConfig()
{
// Arrange
await SeedTestDataAsync();
var config = await _dbContext.GoodsDesignatedPrizes.FirstAsync();
var configId = config.Id;
// Act
var result = await _service.DeleteAsync(configId);
// Assert
Assert.True(result);
var deletedConfig = await _dbContext.GoodsDesignatedPrizes.FindAsync(configId);
Assert.Null(deletedConfig);
}
[Fact]
public async Task DeleteAsync_WithNonExistingConfig_ThrowsException()
{
// Act & Assert
var exception = await Assert.ThrowsAsync<BusinessException>(
() => _service.DeleteAsync(99999));
Assert.Equal(BusinessErrorCodes.NotFound, exception.Code);
Assert.Contains("配置不存在", exception.Message);
}
#endregion
#region Helper Methods
private async Task SeedTestDataAsync()
{
// Create user
var user = new User
{
OpenId = "test_openid",
Uid = "test_uid",
Nickname = "测试用户",
HeadImg = "http://test.com/avatar.jpg",
Mobile = "13800138000",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Users.Add(user);
await _dbContext.SaveChangesAsync();
// Create goods
var goods = new Good
{
Title = "测试商品",
ImgUrl = "http://test.com/goods.jpg",
ImgUrlDetail = "http://test.com/goods_detail.jpg",
Price = 100,
Type = 1,
Status = 1,
Stock = 100,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Goods.Add(goods);
await _dbContext.SaveChangesAsync();
// Create prize
var prize = new GoodsItem
{
GoodsId = goods.Id,
Num = 1,
Title = "A赏",
ImgUrl = "http://test.com/prize.jpg",
Stock = 1,
SurplusStock = 1,
Price = 500,
Money = 300,
ScMoney = 250,
RealPro = 1,
GoodsType = 1,
PrizeCode = "PC001",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.GoodsItems.Add(prize);
await _dbContext.SaveChangesAsync();
// Create designated prize config
var config = new GoodsDesignatedPrize
{
GoodsId = goods.Id,
GoodsItemId = prize.Id,
UserId = user.Id,
IsActive = true,
Remark = "测试配置",
CreatedAt = DateTime.Now
};
_dbContext.GoodsDesignatedPrizes.Add(config);
await _dbContext.SaveChangesAsync();
}
private async Task SeedGoodsWithPrizesAndUsersAsync()
{
// Create user
var user = new User
{
OpenId = "test_openid",
Uid = "test_uid",
Nickname = "测试用户",
HeadImg = "http://test.com/avatar.jpg",
Mobile = "13800138000",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Users.Add(user);
await _dbContext.SaveChangesAsync();
// Create goods
var goods = new Good
{
Title = "测试商品",
ImgUrl = "http://test.com/goods.jpg",
ImgUrlDetail = "http://test.com/goods_detail.jpg",
Price = 100,
Type = 1,
Status = 1,
Stock = 100,
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
};
_dbContext.Goods.Add(goods);
await _dbContext.SaveChangesAsync();
// Create prizes
var prizes = new List<GoodsItem>
{
new()
{
GoodsId = goods.Id,
Num = 1,
Title = "A赏",
ImgUrl = "http://test.com/prize1.jpg",
Stock = 1,
SurplusStock = 1,
Price = 500,
Money = 300,
ScMoney = 250,
RealPro = 1,
GoodsType = 1,
PrizeCode = "PC001",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
},
new()
{
GoodsId = goods.Id,
Num = 2,
Title = "B赏",
ImgUrl = "http://test.com/prize2.jpg",
Stock = 5,
SurplusStock = 5,
Price = 200,
Money = 100,
ScMoney = 80,
RealPro = 5,
GoodsType = 1,
PrizeCode = "PC002",
CreatedAt = DateTime.Now,
UpdatedAt = DateTime.Now
}
};
_dbContext.GoodsItems.AddRange(prizes);
await _dbContext.SaveChangesAsync();
}
#endregion
}