|
@@ -1,4 +1,4 @@
|
|
|
-import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
|
|
|
|
|
+import { describe, it, expect, beforeEach } from 'vitest';
|
|
|
import { testClient } from 'hono/testing';
|
|
import { testClient } from 'hono/testing';
|
|
|
import {
|
|
import {
|
|
|
IntegrationTestDatabase,
|
|
IntegrationTestDatabase,
|
|
@@ -14,20 +14,27 @@ import { AuthService } from '@d8d/core-module-mt/auth-module-mt';
|
|
|
import { UserServiceMt } from '@d8d/core-module-mt/user-module-mt';
|
|
import { UserServiceMt } from '@d8d/core-module-mt/user-module-mt';
|
|
|
import { redisUtil } from '@d8d/shared-utils';
|
|
import { redisUtil } from '@d8d/shared-utils';
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 格式化租户系统配置的Redis键(测试用辅助函数)
|
|
|
|
|
+ */
|
|
|
|
|
+function formatTenantConfigKey(tenantId: number, configKey: string): string {
|
|
|
|
|
+ return `system_config:${tenantId}:${configKey}`;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// 设置集成测试钩子
|
|
// 设置集成测试钩子
|
|
|
setupIntegrationDatabaseHooksWithEntities([SystemConfigMt, UserEntityMt, RoleMt, FileMt])
|
|
setupIntegrationDatabaseHooksWithEntities([SystemConfigMt, UserEntityMt, RoleMt, FileMt])
|
|
|
|
|
|
|
|
describe('系统配置Redis缓存集成测试', () => {
|
|
describe('系统配置Redis缓存集成测试', () => {
|
|
|
- let client: ReturnType<typeof testClient<typeof systemConfigRoutesMt>>;
|
|
|
|
|
|
|
+ let _client: ReturnType<typeof testClient<typeof systemConfigRoutesMt>>;
|
|
|
let authService: AuthService;
|
|
let authService: AuthService;
|
|
|
let userService: UserServiceMt;
|
|
let userService: UserServiceMt;
|
|
|
let systemConfigService: SystemConfigServiceMt;
|
|
let systemConfigService: SystemConfigServiceMt;
|
|
|
- let testToken: string;
|
|
|
|
|
|
|
+ let _testToken: string;
|
|
|
let testUser: any;
|
|
let testUser: any;
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
beforeEach(async () => {
|
|
|
// 创建测试客户端
|
|
// 创建测试客户端
|
|
|
- client = testClient(systemConfigRoutesMt);
|
|
|
|
|
|
|
+ _client = testClient(systemConfigRoutesMt);
|
|
|
|
|
|
|
|
// 获取数据源
|
|
// 获取数据源
|
|
|
const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
@@ -46,7 +53,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 生成测试用户的token
|
|
// 生成测试用户的token
|
|
|
- testToken = authService.generateToken(testUser);
|
|
|
|
|
|
|
+ _testToken = authService.generateToken(testUser);
|
|
|
|
|
|
|
|
// 清除测试前的缓存
|
|
// 清除测试前的缓存
|
|
|
await redisUtil.clearTenantSystemConfigs(testUser.tenantId);
|
|
await redisUtil.clearTenantSystemConfigs(testUser.tenantId);
|
|
@@ -55,7 +62,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
describe('缓存命中测试', () => {
|
|
describe('缓存命中测试', () => {
|
|
|
it('应该从缓存中获取配置值', async () => {
|
|
it('应该从缓存中获取配置值', async () => {
|
|
|
// 先创建配置
|
|
// 先创建配置
|
|
|
- const config = await systemConfigService.create({
|
|
|
|
|
|
|
+ const _config = await systemConfigService.create({
|
|
|
configKey: 'app.cache.test',
|
|
configKey: 'app.cache.test',
|
|
|
configValue: 'cached-value',
|
|
configValue: 'cached-value',
|
|
|
description: '缓存测试配置',
|
|
description: '缓存测试配置',
|
|
@@ -67,7 +74,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
expect(firstResult).toBe('cached-value');
|
|
expect(firstResult).toBe('cached-value');
|
|
|
|
|
|
|
|
// 验证缓存已写入
|
|
// 验证缓存已写入
|
|
|
- const cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, 'app.cache.test');
|
|
|
|
|
|
|
+ const cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, 'app.cache.test'));
|
|
|
expect(cachedValue).toBe('cached-value');
|
|
expect(cachedValue).toBe('cached-value');
|
|
|
|
|
|
|
|
// 第二次查询 - 应该从缓存获取
|
|
// 第二次查询 - 应该从缓存获取
|
|
@@ -98,9 +105,10 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
expect(firstResult['app.feature2.enabled']).toBe('false');
|
|
expect(firstResult['app.feature2.enabled']).toBe('false');
|
|
|
|
|
|
|
|
// 验证缓存已写入
|
|
// 验证缓存已写入
|
|
|
- const cachedValues = await redisUtil.getSystemConfigs(testUser.tenantId, ['app.feature1.enabled', 'app.feature2.enabled']);
|
|
|
|
|
- expect(cachedValues['app.feature1.enabled']).toBe('true');
|
|
|
|
|
- expect(cachedValues['app.feature2.enabled']).toBe('false');
|
|
|
|
|
|
|
+ const cacheKeys = ['app.feature1.enabled', 'app.feature2.enabled'].map(key => formatTenantConfigKey(testUser.tenantId, key));
|
|
|
|
|
+ const cachedValues = await redisUtil.getSystemConfigs(cacheKeys);
|
|
|
|
|
+ expect(cachedValues[cacheKeys[0]]).toBe('true');
|
|
|
|
|
+ expect(cachedValues[cacheKeys[1]]).toBe('false');
|
|
|
|
|
|
|
|
// 第二次批量查询 - 应该从缓存获取
|
|
// 第二次批量查询 - 应该从缓存获取
|
|
|
const secondResult = await systemConfigService.getConfigsByKeys(
|
|
const secondResult = await systemConfigService.getConfigsByKeys(
|
|
@@ -115,7 +123,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
describe('缓存失效测试', () => {
|
|
describe('缓存失效测试', () => {
|
|
|
it('应该在配置更新时清除缓存', async () => {
|
|
it('应该在配置更新时清除缓存', async () => {
|
|
|
// 创建配置
|
|
// 创建配置
|
|
|
- const config = await systemConfigService.create({
|
|
|
|
|
|
|
+ const _config = await systemConfigService.create({
|
|
|
configKey: 'app.update.test',
|
|
configKey: 'app.update.test',
|
|
|
configValue: 'initial-value',
|
|
configValue: 'initial-value',
|
|
|
tenantId: testUser.tenantId
|
|
tenantId: testUser.tenantId
|
|
@@ -125,14 +133,14 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
await systemConfigService.getConfigByKey('app.update.test', testUser.tenantId);
|
|
await systemConfigService.getConfigByKey('app.update.test', testUser.tenantId);
|
|
|
|
|
|
|
|
// 验证缓存已写入
|
|
// 验证缓存已写入
|
|
|
- let cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, 'app.update.test');
|
|
|
|
|
|
|
+ let cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, 'app.update.test'));
|
|
|
expect(cachedValue).toBe('initial-value');
|
|
expect(cachedValue).toBe('initial-value');
|
|
|
|
|
|
|
|
// 更新配置
|
|
// 更新配置
|
|
|
await systemConfigService.setConfig('app.update.test', 'updated-value', testUser.tenantId, '更新后的描述');
|
|
await systemConfigService.setConfig('app.update.test', 'updated-value', testUser.tenantId, '更新后的描述');
|
|
|
|
|
|
|
|
// 验证缓存已清除
|
|
// 验证缓存已清除
|
|
|
- cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, 'app.update.test');
|
|
|
|
|
|
|
+ cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, 'app.update.test'));
|
|
|
expect(cachedValue).toBeNull();
|
|
expect(cachedValue).toBeNull();
|
|
|
|
|
|
|
|
// 再次查询应该从数据库获取新值
|
|
// 再次查询应该从数据库获取新值
|
|
@@ -142,7 +150,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
|
|
|
|
|
it('应该在配置删除时清除缓存', async () => {
|
|
it('应该在配置删除时清除缓存', async () => {
|
|
|
// 创建配置
|
|
// 创建配置
|
|
|
- const config = await systemConfigService.create({
|
|
|
|
|
|
|
+ const _config = await systemConfigService.create({
|
|
|
configKey: 'app.delete.test',
|
|
configKey: 'app.delete.test',
|
|
|
configValue: 'to-be-deleted',
|
|
configValue: 'to-be-deleted',
|
|
|
tenantId: testUser.tenantId
|
|
tenantId: testUser.tenantId
|
|
@@ -152,14 +160,14 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
await systemConfigService.getConfigByKey('app.delete.test', testUser.tenantId);
|
|
await systemConfigService.getConfigByKey('app.delete.test', testUser.tenantId);
|
|
|
|
|
|
|
|
// 验证缓存已写入
|
|
// 验证缓存已写入
|
|
|
- let cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, 'app.delete.test');
|
|
|
|
|
|
|
+ let cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, 'app.delete.test'));
|
|
|
expect(cachedValue).toBe('to-be-deleted');
|
|
expect(cachedValue).toBe('to-be-deleted');
|
|
|
|
|
|
|
|
// 删除配置
|
|
// 删除配置
|
|
|
await systemConfigService.deleteConfig('app.delete.test', testUser.tenantId);
|
|
await systemConfigService.deleteConfig('app.delete.test', testUser.tenantId);
|
|
|
|
|
|
|
|
// 验证缓存已清除
|
|
// 验证缓存已清除
|
|
|
- cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, 'app.delete.test');
|
|
|
|
|
|
|
+ cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, 'app.delete.test'));
|
|
|
expect(cachedValue).toBeNull();
|
|
expect(cachedValue).toBeNull();
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
@@ -173,7 +181,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
expect(firstResult).toBeNull();
|
|
expect(firstResult).toBeNull();
|
|
|
|
|
|
|
|
// 验证空值缓存已设置
|
|
// 验证空值缓存已设置
|
|
|
- const cachedValue = await redisUtil.getSystemConfig(testUser.tenantId, nonExistentKey);
|
|
|
|
|
|
|
+ const cachedValue = await redisUtil.getSystemConfig(formatTenantConfigKey(testUser.tenantId, nonExistentKey));
|
|
|
expect(redisUtil.isNullValue(cachedValue)).toBe(true);
|
|
expect(redisUtil.isNullValue(cachedValue)).toBe(true);
|
|
|
|
|
|
|
|
// 第二次查询应该从空值缓存返回null
|
|
// 第二次查询应该从空值缓存返回null
|
|
@@ -202,22 +210,23 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
expect(result[nonExistentKey]).toBeUndefined();
|
|
expect(result[nonExistentKey]).toBeUndefined();
|
|
|
|
|
|
|
|
// 验证空值缓存已设置
|
|
// 验证空值缓存已设置
|
|
|
- const cachedValues = await redisUtil.getSystemConfigs(testUser.tenantId, [existentKey, nonExistentKey]);
|
|
|
|
|
- expect(cachedValues[existentKey]).toBe('existent-value');
|
|
|
|
|
- expect(redisUtil.isNullValue(cachedValues[nonExistentKey])).toBe(true);
|
|
|
|
|
|
|
+ const cacheKeys = [existentKey, nonExistentKey].map(key => formatTenantConfigKey(testUser.tenantId, key));
|
|
|
|
|
+ const cachedValues = await redisUtil.getSystemConfigs(cacheKeys);
|
|
|
|
|
+ expect(cachedValues[cacheKeys[0]]).toBe('existent-value');
|
|
|
|
|
+ expect(redisUtil.isNullValue(cachedValues[cacheKeys[1]])).toBe(true);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
describe('多租户缓存隔离测试', () => {
|
|
describe('多租户缓存隔离测试', () => {
|
|
|
- let tenant1User: any;
|
|
|
|
|
- let tenant2User: any;
|
|
|
|
|
|
|
+ let _tenant1User: any;
|
|
|
|
|
+ let _tenant2User: any;
|
|
|
|
|
|
|
|
beforeEach(async () => {
|
|
beforeEach(async () => {
|
|
|
const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
const dataSource = await IntegrationTestDatabase.getDataSource();
|
|
|
if (!dataSource) throw new Error('Database not initialized');
|
|
if (!dataSource) throw new Error('Database not initialized');
|
|
|
|
|
|
|
|
// 创建租户1的用户
|
|
// 创建租户1的用户
|
|
|
- tenant1User = await TestDataFactory.createTestUser(dataSource, {
|
|
|
|
|
|
|
+ _tenant1User = await TestDataFactory.createTestUser(dataSource, {
|
|
|
username: 'tenant1_user_cache',
|
|
username: 'tenant1_user_cache',
|
|
|
password: 'TestPassword123!',
|
|
password: 'TestPassword123!',
|
|
|
email: 'tenant1_cache@example.com',
|
|
email: 'tenant1_cache@example.com',
|
|
@@ -225,7 +234,7 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 创建租户2的用户
|
|
// 创建租户2的用户
|
|
|
- tenant2User = await TestDataFactory.createTestUser(dataSource, {
|
|
|
|
|
|
|
+ _tenant2User = await TestDataFactory.createTestUser(dataSource, {
|
|
|
username: 'tenant2_user_cache',
|
|
username: 'tenant2_user_cache',
|
|
|
password: 'TestPassword123!',
|
|
password: 'TestPassword123!',
|
|
|
email: 'tenant2_cache@example.com',
|
|
email: 'tenant2_cache@example.com',
|
|
@@ -263,8 +272,8 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
expect(tenant2Result).toBe('tenant2-value');
|
|
expect(tenant2Result).toBe('tenant2-value');
|
|
|
|
|
|
|
|
// 验证缓存隔离
|
|
// 验证缓存隔离
|
|
|
- const tenant1Cached = await redisUtil.getSystemConfig(1, sharedConfigKey);
|
|
|
|
|
- const tenant2Cached = await redisUtil.getSystemConfig(2, sharedConfigKey);
|
|
|
|
|
|
|
+ const tenant1Cached = await redisUtil.getSystemConfig(formatTenantConfigKey(1, sharedConfigKey));
|
|
|
|
|
+ const tenant2Cached = await redisUtil.getSystemConfig(formatTenantConfigKey(2, sharedConfigKey));
|
|
|
expect(tenant1Cached).toBe('tenant1-value');
|
|
expect(tenant1Cached).toBe('tenant1-value');
|
|
|
expect(tenant2Cached).toBe('tenant2-value');
|
|
expect(tenant2Cached).toBe('tenant2-value');
|
|
|
});
|
|
});
|
|
@@ -289,15 +298,13 @@ describe('系统配置Redis缓存集成测试', () => {
|
|
|
await systemConfigService.warmUpCache(testUser.tenantId);
|
|
await systemConfigService.warmUpCache(testUser.tenantId);
|
|
|
|
|
|
|
|
// 验证缓存已预热
|
|
// 验证缓存已预热
|
|
|
- const cachedValues = await redisUtil.getSystemConfigs(testUser.tenantId, [
|
|
|
|
|
- 'app.login.enabled',
|
|
|
|
|
- 'app.payment.enabled',
|
|
|
|
|
- 'app.notification.enabled'
|
|
|
|
|
- ]);
|
|
|
|
|
-
|
|
|
|
|
- expect(cachedValues['app.login.enabled']).toBe('true');
|
|
|
|
|
- expect(cachedValues['app.payment.enabled']).toBe('false');
|
|
|
|
|
- expect(redisUtil.isNullValue(cachedValues['app.notification.enabled'])).toBe(true);
|
|
|
|
|
|
|
+ const warmupKeys = ['app.login.enabled', 'app.payment.enabled', 'app.notification.enabled'];
|
|
|
|
|
+ const cacheKeys = warmupKeys.map(key => formatTenantConfigKey(testUser.tenantId, key));
|
|
|
|
|
+ const cachedValues = await redisUtil.getSystemConfigs(cacheKeys);
|
|
|
|
|
+
|
|
|
|
|
+ expect(cachedValues[cacheKeys[0]]).toBe('true');
|
|
|
|
|
+ expect(cachedValues[cacheKeys[1]]).toBe('false');
|
|
|
|
|
+ expect(redisUtil.isNullValue(cachedValues[cacheKeys[2]])).toBe(true);
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|
|
|
});
|
|
});
|