import { ConflictException, NotFoundException } from '@nestjs/common'; import { jest } from '@jest/globals'; import { UsersService } from './users.service.js'; import type { PrismaService } from '../prisma.service.js'; describe('UsersService.bindOpenIdForMiniAppLogin', () => { function createService() { const prisma = { user: { findUnique: jest.fn(), update: jest.fn(), }, } as unknown as PrismaService; return { prisma, service: new UsersService(prisma), }; } it('允许同一个 openId 绑定多个院内账号', async () => { const { prisma, service } = createService(); const sharedOpenId = 'shared-openid'; (prisma.user.findUnique as jest.Mock) .mockResolvedValueOnce({ id: 1, openId: null }) .mockResolvedValueOnce({ id: 2, openId: null }); (prisma.user.update as jest.Mock).mockResolvedValue(undefined); await service.bindOpenIdForMiniAppLogin(1, sharedOpenId); await service.bindOpenIdForMiniAppLogin(2, sharedOpenId); expect(prisma.user.update).toHaveBeenNthCalledWith(1, { where: { id: 1 }, data: { openId: sharedOpenId }, }); expect(prisma.user.update).toHaveBeenNthCalledWith(2, { where: { id: 2 }, data: { openId: sharedOpenId }, }); }); it('拒绝用新的微信账号覆盖已绑定院内账号', async () => { const { prisma, service } = createService(); (prisma.user.findUnique as jest.Mock).mockResolvedValue({ id: 1, openId: 'bound-openid', }); await expect( service.bindOpenIdForMiniAppLogin(1, 'other-openid'), ).rejects.toThrow(new ConflictException('当前院内账号已绑定其他微信账号')); expect(prisma.user.update).not.toHaveBeenCalled(); }); it('目标院内账号不存在时返回 404', async () => { const { prisma, service } = createService(); (prisma.user.findUnique as jest.Mock).mockResolvedValue(null); await expect( service.bindOpenIdForMiniAppLogin(999, 'shared-openid'), ).rejects.toThrow(new NotFoundException('用户不存在')); }); });