import { expect } from 'chai' import db, { DbQueryCache } from '../../src/db/index.js' import { UserModel } from '../../src/db/models/UserModel.js' describe('Query Cache', () => { before(async () => { // 确保users表存在 const exists = await db.schema.hasTable('users') if (!exists) { await db.schema.createTable('users', (table) => { table.increments('id').primary() table.string('username').unique() table.string('email').unique() table.string('password') table.timestamp('created_at').defaultTo(db.fn.now()) table.timestamp('updated_at').defaultTo(db.fn.now()) }) } // 清空缓存 DbQueryCache.clear() }) afterEach(async () => { // 清理测试数据 await db('users').del() // 清空缓存 DbQueryCache.clear() }) describe('Cache Basic Operations', () => { it('应该正确设置和获取缓存', async () => { const key = 'test_key' const value = { data: 'test_value', timestamp: Date.now() } DbQueryCache.set(key, value, 1000) // 1秒过期 const cached = DbQueryCache.get(key) expect(cached).to.deep.equal(value) }) it('应该正确检查缓存存在性', async () => { const key = 'existence_test' expect(DbQueryCache.has(key)).to.be.false DbQueryCache.set(key, 'test_value', 1000) expect(DbQueryCache.has(key)).to.be.true }) it('应该正确删除缓存', async () => { const key = 'delete_test' DbQueryCache.set(key, 'test_value', 1000) expect(DbQueryCache.has(key)).to.be.true DbQueryCache.delete(key) expect(DbQueryCache.has(key)).to.be.false }) it('应该正确清空所有缓存', async () => { DbQueryCache.set('key1', 'value1', 1000) DbQueryCache.set('key2', 'value2', 1000) const statsBefore = DbQueryCache.stats() expect(statsBefore.valid).to.be.greaterThan(0) DbQueryCache.clear() const statsAfter = DbQueryCache.stats() expect(statsAfter.valid).to.equal(0) }) }) describe('Query Builder Cache', () => { beforeEach(async () => { // 创建测试用户 await UserModel.create({ username: 'cache_test', email: 'cache_test@example.com', password: 'password123' }) }) it('应该正确缓存查询结果', async () => { // 第一次查询(应该执行数据库查询) const result1 = await db('users') .where('username', 'cache_test') .cache(5000) // 5秒缓存 expect(result1).to.have.length(1) expect(result1[0].username).to.equal('cache_test') // 修改数据库中的数据 await db('users') .where('username', 'cache_test') .update({ name: 'Cached User' }) // 第二次查询(应该从缓存获取,不会看到更新) const result2 = await db('users') .where('username', 'cache_test') .cache(5000) expect(result2).to.have.length(1) expect(result2[0]).to.not.have.property('name') // 缓存的结果不会有新添加的字段 }) it('应该支持自定义缓存键', async () => { const result = await db('users') .where('username', 'cache_test') .cacheAs('custom_cache_key') .cache(5000) // 检查自定义键是否在缓存中 expect(DbQueryCache.has('custom_cache_key')).to.be.true }) it('应该正确使缓存失效', async () => { // 设置缓存 await db('users') .where('username', 'cache_test') .cacheAs('invalidate_test') .cache(5000) expect(DbQueryCache.has('invalidate_test')).to.be.true // 使缓存失效 await db('users') .where('username', 'cache_test') .cacheInvalidate() // 检查缓存是否已清除 expect(DbQueryCache.has('invalidate_test')).to.be.false }) it('应该按前缀清理缓存', async () => { // 设置多个缓存项 await db('users').where('id', 1).cacheAs('user:1:data').cache(5000) await db('users').where('id', 2).cacheAs('user:2:data').cache(5000) await db('posts').where('id', 1).cacheAs('post:1:data').cache(5000) // 检查缓存项存在 expect(DbQueryCache.has('user:1:data')).to.be.true expect(DbQueryCache.has('user:2:data')).to.be.true expect(DbQueryCache.has('post:1:data')).to.be.true // 按前缀清理 await db('users').cacheInvalidateByPrefix('user:') // 检查清理结果 expect(DbQueryCache.has('user:1:data')).to.be.false expect(DbQueryCache.has('user:2:data')).to.be.false expect(DbQueryCache.has('post:1:data')).to.be.true // 不受影响 }) }) describe('Cache Expiration', () => { it('应该正确处理缓存过期', async () => { const key = 'expire_test' DbQueryCache.set(key, 'test_value', 10) // 10ms过期 // 立即检查应该存在 expect(DbQueryCache.has(key)).to.be.true expect(DbQueryCache.get(key)).to.equal('test_value') // 等待过期 await new Promise(resolve => setTimeout(resolve, 20)) // 检查应该已过期 expect(DbQueryCache.has(key)).to.be.false expect(DbQueryCache.get(key)).to.be.undefined }) it('应该正确清理过期缓存', async () => { // 设置一些会过期的缓存项 DbQueryCache.set('expired_1', 'value1', 10) // 10ms过期 DbQueryCache.set('expired_2', 'value2', 10) // 10ms过期 DbQueryCache.set('valid', 'value3', 5000) // 5秒过期 // 检查初始状态 const statsBefore = DbQueryCache.stats() expect(statsBefore.size).to.equal(3) // 等待过期 await new Promise(resolve => setTimeout(resolve, 20)) // 清理过期缓存 const cleaned = DbQueryCache.cleanup() expect(cleaned).to.be.greaterThanOrEqual(2) // 检查最终状态 const statsAfter = DbQueryCache.stats() expect(statsAfter.size).to.equal(1) // 只剩下valid项 expect(DbQueryCache.has('valid')).to.be.true }) }) describe('Cache Statistics', () => { it('应该正确报告缓存统计', async () => { // 清空并设置一些测试数据 DbQueryCache.clear() DbQueryCache.set('stat_test_1', 'value1', 5000) DbQueryCache.set('stat_test_2', 'value2', 10) // 将过期 await new Promise(resolve => setTimeout(resolve, 20)) // 等待过期 const stats = DbQueryCache.stats() expect(stats).to.have.property('size') expect(stats).to.have.property('valid') expect(stats).to.have.property('expired') expect(stats).to.have.property('totalSize') expect(stats).to.have.property('averageSize') }) }) })