Rails 4.2自定义缓存存储测试失败:数据库备份功能无效
问题分析与解决方案
看起来你的问题出在测试执行顺序导致的缓存命中上,而不是备份逻辑本身有问题。
核心原因
第一个测试caches data运行时,已经通过fetch把数据写入了文件缓存。当第二个测试backs up to db when asked运行时,fetch发现缓存已经存在,直接返回了缓存值,根本没有执行你传入的block——自然也就不会调用write方法,DB备份逻辑根本没机会运行。
这也是为什么你直接调用write方法测试正常:write不管缓存是否存在都会执行,而fetch只有在缓存miss的时候才会触发block和后续的write。
解决方案
你需要确保每个测试都在干净的环境中运行,避免测试间的缓存干扰。有两种简单的方式:
1. 每个测试前清空缓存与DB备份
在测试块中添加before钩子,每次测试前清空缓存和CacheBackup记录:
describe FileStoreWithDbBackup do let(:store) { FileStoreWithDbBackup.new 'tmp/cache/' } let(:key) { 'data key' } let(:payload) { 'data value' } # 每次测试前重置环境 before do store.clear # 清空文件缓存 CacheBackup.delete_all # 清空数据库备份记录 end it 'caches data' do # ... 原测试代码不变 end it 'backs up to db when asked' do store.fetch(key, expires_in: 1.day, backup: true) { payload } # 注意:Rails 4.2中find_by_name已被弃用,改用find_by(name: ...) backup = CacheBackup.find_by(name: key) _(backup.value).must_equal payload _(backup.expires).must_be_close_to 1.day.from_now end end
2. 在fetch中使用:force选项强制执行block
如果不想每次清空缓存,可以在第二个测试的fetch中添加:force => true选项,强制绕过缓存直接执行block并调用write:
it 'backs up to db when asked' do # 添加force: true,强制执行block并写入缓存 store.fetch(key, expires_in: 1.day, backup: true, force: true) { payload } backup = CacheBackup.find_by(name: key) _(backup.value).must_equal payload _(backup.expires).must_be_close_to 1.day.from_now end
额外小提示
- Rails 4.2中
find_by_name这种动态finder已经被弃用,建议统一使用find_by(name: key)写法,避免警告。 - 可以在
write方法中加个日志打印options.inspect,方便调试时确认backup参数是否正确传递:def write(name, value, options = nil) super(name, value, options) Rails.logger.debug("Write called with options: #{options.inspect}") if options[:backup] # ... 原备份逻辑 end end
内容的提问来源于stack exchange,提问作者Toby 1 Kenobi
相关产品推荐
相关产品推荐

