You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

212 lines
7.8 KiB

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')
})
})
})