You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:09:46