forked from datawhale/whale-town-end
test(email, verification, login): 更新测试中的断言内容, 修复测试error.
- Replace boolean assertions with structured result object checks in email service tests - Update email service tests to verify success flag and isTestMode property - Add error message assertions for failed email sending scenarios - Change logger spy from 'log' to 'warn' for test mode email output - Update test message to clarify emails are not actually sent in test mode - Add code and createdAt properties to verification code stats mock data - Fix TTL mock value from -1 to -2 to correctly represent non-existent keys - Replace Inject decorator with direct UsersService type injection in LoginCoreService - Ensure verification service tests properly mock TTL values during code verification - Improve test coverage by validating complete response structures instead of simple booleans
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
import { Injectable, UnauthorizedException, ConflictException, NotFoundException, BadRequestException, Inject } from '@nestjs/common';
|
import { Injectable, UnauthorizedException, ConflictException, NotFoundException, BadRequestException, Inject } from '@nestjs/common';
|
||||||
import { Users } from '../db/users/users.entity';
|
import { Users } from '../db/users/users.entity';
|
||||||
|
import { UsersService } from '../db/users/users.service';
|
||||||
import { EmailService, EmailSendResult } from '../utils/email/email.service';
|
import { EmailService, EmailSendResult } from '../utils/email/email.service';
|
||||||
import { VerificationService, VerificationCodeType } from '../utils/verification/verification.service';
|
import { VerificationService, VerificationCodeType } from '../utils/verification/verification.service';
|
||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
@@ -102,7 +103,7 @@ export interface VerificationCodeResult {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class LoginCoreService {
|
export class LoginCoreService {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject('UsersService') private readonly usersService: any,
|
private readonly usersService: UsersService,
|
||||||
private readonly emailService: EmailService,
|
private readonly emailService: EmailService,
|
||||||
private readonly verificationService: VerificationService,
|
private readonly verificationService: VerificationService,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendEmail(emailOptions);
|
const result = await service.sendEmail(emailOptions);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.isTestMode).toBe(false);
|
||||||
expect(mockTransporter.sendMail).toHaveBeenCalledWith({
|
expect(mockTransporter.sendMail).toHaveBeenCalledWith({
|
||||||
from: '"Test Sender" <noreply@test.com>',
|
from: '"Test Sender" <noreply@test.com>',
|
||||||
to: 'test@example.com',
|
to: 'test@example.com',
|
||||||
@@ -138,7 +139,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendEmail(emailOptions);
|
const result = await service.sendEmail(emailOptions);
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
|
expect(result.error).toBe('发送失败');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('应该在测试模式下输出邮件内容', async () => {
|
it('应该在测试模式下输出邮件内容', async () => {
|
||||||
@@ -157,13 +159,14 @@ describe('EmailService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Mock the service to use test transporter
|
// Mock the service to use test transporter
|
||||||
const loggerSpy = jest.spyOn(service['logger'], 'log').mockImplementation();
|
const loggerSpy = jest.spyOn(service['logger'], 'warn').mockImplementation();
|
||||||
service['transporter'] = testTransporter;
|
service['transporter'] = testTransporter;
|
||||||
|
|
||||||
const result = await service.sendEmail(emailOptions);
|
const result = await service.sendEmail(emailOptions);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
expect(loggerSpy).toHaveBeenCalledWith('=== 邮件发送(测试模式) ===');
|
expect(result.isTestMode).toBe(true);
|
||||||
|
expect(loggerSpy).toHaveBeenCalledWith('=== 邮件发送(测试模式 - 邮件未真实发送) ===');
|
||||||
|
|
||||||
loggerSpy.mockRestore();
|
loggerSpy.mockRestore();
|
||||||
});
|
});
|
||||||
@@ -183,7 +186,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendVerificationCode(options);
|
const result = await service.sendVerificationCode(options);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.isTestMode).toBe(false);
|
||||||
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
to: 'test@example.com',
|
to: 'test@example.com',
|
||||||
@@ -206,7 +210,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendVerificationCode(options);
|
const result = await service.sendVerificationCode(options);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.isTestMode).toBe(false);
|
||||||
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
to: 'test@example.com',
|
to: 'test@example.com',
|
||||||
@@ -227,7 +232,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendVerificationCode(options);
|
const result = await service.sendVerificationCode(options);
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
|
expect(result.error).toBe('发送失败');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -238,7 +244,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendWelcomeEmail('test@example.com', '测试用户');
|
const result = await service.sendWelcomeEmail('test@example.com', '测试用户');
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
|
expect(result.isTestMode).toBe(false);
|
||||||
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
expect(mockTransporter.sendMail).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
to: 'test@example.com',
|
to: 'test@example.com',
|
||||||
@@ -253,7 +260,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendWelcomeEmail('test@example.com', '测试用户');
|
const result = await service.sendWelcomeEmail('test@example.com', '测试用户');
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
|
expect(result.error).toBe('发送失败');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -358,7 +366,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendEmail(emailOptions);
|
const result = await service.sendEmail(emailOptions);
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
|
expect(result.error).toBe('ECONNREFUSED');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('应该正确处理认证错误', async () => {
|
it('应该正确处理认证错误', async () => {
|
||||||
@@ -372,7 +381,8 @@ describe('EmailService', () => {
|
|||||||
|
|
||||||
const result = await service.sendEmail(emailOptions);
|
const result = await service.sendEmail(emailOptions);
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result.success).toBe(false);
|
||||||
|
expect(result.error).toBe('Invalid login');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('应该正确处理连接验证错误', async () => {
|
it('应该正确处理连接验证错误', async () => {
|
||||||
|
|||||||
@@ -272,6 +272,7 @@ describe('VerificationService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
mockRedis.get.mockResolvedValue(JSON.stringify(codeInfo));
|
mockRedis.get.mockResolvedValue(JSON.stringify(codeInfo));
|
||||||
|
mockRedis.ttl.mockResolvedValue(240); // Mock TTL 返回 240 秒
|
||||||
|
|
||||||
await expect(service.verifyCode(email, type, '654321')).rejects.toThrow(
|
await expect(service.verifyCode(email, type, '654321')).rejects.toThrow(
|
||||||
new BadRequestException('验证码错误,剩余尝试次数: 1')
|
new BadRequestException('验证码错误,剩余尝试次数: 1')
|
||||||
@@ -285,7 +286,7 @@ describe('VerificationService', () => {
|
|||||||
expect(mockRedis.set).toHaveBeenCalledWith(
|
expect(mockRedis.set).toHaveBeenCalledWith(
|
||||||
`verification_code:${type}:${email}`,
|
`verification_code:${type}:${email}`,
|
||||||
JSON.stringify(updatedCodeInfo),
|
JSON.stringify(updatedCodeInfo),
|
||||||
300
|
240
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -298,6 +299,7 @@ describe('VerificationService', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
mockRedis.get.mockResolvedValue(JSON.stringify(codeInfo));
|
mockRedis.get.mockResolvedValue(JSON.stringify(codeInfo));
|
||||||
|
mockRedis.ttl.mockResolvedValue(240); // Mock TTL 返回 240 秒
|
||||||
|
|
||||||
await expect(service.verifyCode(email, type, '654321')).rejects.toThrow(
|
await expect(service.verifyCode(email, type, '654321')).rejects.toThrow(
|
||||||
new BadRequestException('验证码错误,剩余尝试次数: 0')
|
new BadRequestException('验证码错误,剩余尝试次数: 0')
|
||||||
@@ -391,18 +393,20 @@ describe('VerificationService', () => {
|
|||||||
ttl: 240,
|
ttl: 240,
|
||||||
attempts: 1,
|
attempts: 1,
|
||||||
maxAttempts: 3,
|
maxAttempts: 3,
|
||||||
|
code: '123456',
|
||||||
|
createdAt: expect.any(Number),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('应该在验证码不存在时返回基本信息', async () => {
|
it('应该在验证码不存在时返回基本信息', async () => {
|
||||||
mockRedis.exists.mockResolvedValue(false);
|
mockRedis.exists.mockResolvedValue(false);
|
||||||
mockRedis.ttl.mockResolvedValue(-1);
|
mockRedis.ttl.mockResolvedValue(-2); // -2 表示键不存在
|
||||||
|
|
||||||
const result = await service.getCodeStats(email, type);
|
const result = await service.getCodeStats(email, type);
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
exists: false,
|
exists: false,
|
||||||
ttl: -1,
|
ttl: -2, // 修改为 -2
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user