add(test):添加单元测试

This commit is contained in:
2025-12-07 15:44:51 +08:00
170 changed files with 14260 additions and 18 deletions
+21 -1
View File
@@ -20,7 +20,7 @@ namespace IM_API.Configs
.ForMember(dest => dest.Avatar,opt => opt.MapFrom(src => "https://ts1.tc.mm.bing.net/th/id/OIP-C.dl0WpkTP6E2J4FnhDC_jHwAAAA?rs=1&pid=ImgDetMain&o=7&rm=3"))
.ForMember(dest => dest.StatusEnum,opt => opt.MapFrom(src => UserStatus.Normal))
.ForMember(dest => dest.OnlineStatusEnum,opt => opt.MapFrom(src => UserOnlineStatus.Offline))
.ForMember(dest => dest.NickName,opt => opt.MapFrom(src => src.NickName))
.ForMember(dest => dest.NickName,opt => opt.MapFrom(src => src.NickName??"默认用户"))
.ForMember(dest => dest.Created,opt => opt.MapFrom(src => DateTime.Now))
.ForMember(dest => dest.IsDeleted,opt => opt.MapFrom(src => 0))
;
@@ -42,6 +42,26 @@ namespace IM_API.Configs
.ForMember(dest => dest.StateEnum , opt => opt.MapFrom(src => FriendRequestState.Pending))
.ForMember(dest => dest.Description , opt => opt.MapFrom(src => src.Description))
;
//消息模型转换
CreateMap<Message, MessageBaseDto>()
.ForMember(dest => dest.Type , opt => opt.MapFrom(src => src.MsgTypeEnum.ToString()))
.ForMember(dest => dest.MsgId , opt => opt.MapFrom(src => src.Id))
.ForMember(dest => dest.SenderId , opt => opt.MapFrom(src => src.Sender))
.ForMember(dest => dest.ChatType , opt => opt.MapFrom(src => src.ChatTypeEnum.ToString()))
.ForMember(dest => dest.ReceiverId, opt => opt.MapFrom(src => src.Recipient))
.ForMember(dest => dest.Content, opt => opt.MapFrom(src => src.Content))
.ForMember(dest => dest.TimeStamp, opt => opt.MapFrom(src => src.Created))
;
CreateMap<MessageBaseDto, Message>()
.ForMember(dest => dest.Sender, opt => opt.MapFrom(src => src.SenderId))
.ForMember(dest => dest.ChatTypeEnum,opt => opt.MapFrom(src => src.ChatType))
.ForMember(dest => dest.MsgTypeEnum, opt => opt.MapFrom(src => src.Type))
.ForMember(dest => dest.Created, opt => opt.MapFrom(src => src.TimeStamp))
.ForMember(dest => dest.Content, opt => opt.MapFrom(src => src.Content))
.ForMember(dest => dest.Recipient, opt => opt.MapFrom(src => src.ReceiverId))
.ForMember(dest => dest.StateEnum, opt => opt.MapFrom(src => MessageState.Sent))
;
}
}
}
+5
View File
@@ -0,0 +1,5 @@
namespace IM_API.Dtos
{
public record MessageBaseDto(
string Type,string ChatType, string MsgId,int SenderId,int ReceiverId,string Content,DateTime TimeStamp);
}
+1 -1
View File
@@ -4,6 +4,6 @@
{
public string Username { get; set; }
public string Password { get; set; }
public string NickName { get; set; }
public string? NickName { get; set; }
}
}
+13 -5
View File
@@ -1,4 +1,6 @@
using IM_API.Interface.Services;
using IM_API.Dtos;
using IM_API.Interface.Services;
using IM_API.Tools;
using Microsoft.AspNetCore.SignalR;
using System.Security.Claims;
@@ -12,15 +14,21 @@ namespace IM_API.Hubs
_JWTService = jWTService;
}
public override Task OnConnectedAsync()
public async override Task OnConnectedAsync()
{
var userIdStr = Context.User.FindFirstValue(ClaimTypes.NameIdentifier);
if(userIdStr is null)
{
await Clients.Caller.SendAsync("ReceiveMessage",new BaseResponse<object?>(CodeDefine.AUTH_FAILED));
Context.Abort();
return;
}
int userId = int.Parse(userIdStr);
Console.WriteLine(userId);
return base.OnConnectedAsync();
await base.OnConnectedAsync();
}
public async Task SendMessage(string user,string message)
public async Task SendMessage(MessageBaseDto dto)
{
await Clients.Caller.SendAsync("ReceiveMessage", "qwfqwfqw","test");
}
}
+7 -1
View File
@@ -1,10 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36408.4 d17.14
VisualStudioVersion = 17.14.36408.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IM_API", "IM_API.csproj", "{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IMTest", "..\IMTest\IMTest.csproj", "{9DB9D44A-2D86-45A2-B651-D976277CF324}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F001642C-3E66-4C2C-9A25-1AE5EE76CE97}.Release|Any CPU.Build.0 = Release|Any CPU
{9DB9D44A-2D86-45A2-B651-D976277CF324}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9DB9D44A-2D86-45A2-B651-D976277CF324}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9DB9D44A-2D86-45A2-B651-D976277CF324}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9DB9D44A-2D86-45A2-B651-D976277CF324}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -0,0 +1,55 @@
using IM_API.Dtos;
namespace IM_API.Interface.Services
{
public interface IMessageSevice
{
/// <summary>
/// 发送私聊消息
/// </summary>
/// <param name="senderId">发送人id</param>
/// <param name="receiverId">接收人</param>
/// <param name="dto"></param>
/// <returns></returns>
Task<bool> SendPrivateMessageAsync(int senderId,int receiverId,MessageBaseDto dto);
/// <summary>
/// 发送群聊消息
/// </summary>
/// <param name="senderId">发送人id</param>
/// <param name="groupId">接收群id</param>
/// <param name="dto"></param>
/// <returns></returns>
Task<bool> SendGroupMessageAsync(int senderId,int groupId,MessageBaseDto dto);
/// <summary>
/// 获取私聊消息列表
/// </summary>
/// <param name="userAId"></param>
/// <param name="userBId"></param>
/// <param name="page"></param>
/// <param name="pageSize"></param>
/// <param name="desc"></param>
/// <returns></returns>
Task<List<MessageBaseDto>> GetPrivateMessagesAsync(int userAId,int userBId,int page,int pageSize,bool desc);
/// <summary>
/// 获取群聊消息列表
/// </summary>
/// <param name="groupId"></param>
/// <param name="page"></param>
/// <param name="pageSize"></param>
/// <param name="desc"></param>
/// <returns></returns>
Task<List<MessageBaseDto>> GetGroupMessagesAsync(int groupId, int page, int pageSize, bool desc);
/// <summary>
/// 获取未读消息数
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
Task<int> GetUnreadCountAsync(int userId);
Task<List<MessageBaseDto>> GetUnreadMessagesAsync(int userId);
Task<bool> MarkAsReadAsync(int userId,long messageId);
Task<bool> MarkConversationAsReadAsync(int userId,int? userBId,int? groupId);
Task<bool> RecallMessageAsync(int userId,int messageId);
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace IM_API.Models
{
public enum ChatType
{
PRIVATE = 0,
GROUP = 1
}
}
+10 -3
View File
@@ -49,10 +49,17 @@ public partial class ImContext : DbContext
public virtual DbSet<Role> Roles { get; set; }
public virtual DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
=> optionsBuilder.UseMySql("server=frp-era.com;port=26582;database=IM;user=product;password=12345678", Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.44-mysql"));
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseMySql(
"server=frp-era.com;port=26582;database=IM;user=product;password=12345678",
ServerVersion.Parse("5.7.44-mysql")
);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
+5
View File
@@ -7,6 +7,11 @@
get => (MessageMsgType)MsgType;
set => MsgType = (sbyte) value;
}
public ChatType ChatTypeEnum
{
get => (ChatType)ChatType;
set => ChatType = (sbyte)value;
}
public MessageState StateEnum
{
get => (MessageState)State;
+1 -1
View File
@@ -20,7 +20,7 @@ public partial class User
/// <summary>
/// 用户昵称
/// </summary>
public string NickName { get; set; } = null!;
public string? NickName { get; set; } = null!;
/// <summary>
/// 用户在线状态
+3 -3
View File
@@ -63,7 +63,7 @@ namespace IM_API.Services
public async Task<List<FriendInfoDto>> GetFriendListAsync(int userId, int page, int limit, bool desc)
{
var query = _context.Friends.Where(x => x.UserId == userId && x.StatusEnum == FriendStatus.Added);
var query = _context.Friends.Where(x => x.UserId == userId && x.Status == (sbyte)FriendStatus.Added);
if (desc)
{
query = query.OrderByDescending(x => x.UserId);
@@ -149,14 +149,14 @@ namespace IM_API.Services
if(!isExistUser2) throw new BaseException(CodeDefine.USER_NOT_FOUND);
// 检查是否已有好友关系或待处理请求
bool alreadyExists = await _context.FriendRequests.AnyAsync(x =>
x.RequestUser == dto.FromUserId && x.ResponseUser == dto.ToUserId && x.StateEnum == FriendRequestState.Pending
x.RequestUser == dto.FromUserId && x.ResponseUser == dto.ToUserId && x.State == (sbyte)FriendRequestState.Pending
);
if (alreadyExists)
throw new BaseException(CodeDefine.FRIEND_REQUEST_EXISTS);
//检查是否被对方拉黑
bool isBlocked = await _context.Friends.AnyAsync(x =>
x.UserId == dto.FromUserId && x.FriendId == dto.ToUserId && x.StatusEnum == FriendStatus.Blocked
x.UserId == dto.FromUserId && x.FriendId == dto.ToUserId && x.Status == (sbyte)FriendStatus.Blocked
);
if (isBlocked)
throw new BaseException(CodeDefine.FRIEND_REQUEST_REJECTED);