如何使用Timecop在RSpec中测试账号创建时30天试用到期时间设置逻辑?
问题原因分析
- 第一个测试失败的核心问题是Timecop冻结时机错误:你在执行创建账号的
post请求之后才冻结时间,此时account的trial_ends_at已经用真实的当前时间计算完成,后续在冻结块里调用的30.days.from_now是基于冻结时间点计算的,两者必然不相等。 - 第二个测试不稳定是因为
on_generic_trial?仅判断当前时间是否早于trial_ends_at,只要试用期长于30天,冻结到第30天的时候依然会返回true,完全无法验证试用期长度是不是刚好30天。
正确测试写法
it "sets trial_ends_at to exactly 30 days from creation time" do # 先冻结当前时间,保证所有时间计算都基于同一个基准点 freeze_time = Time.current Timecop.freeze(freeze_time) do # 冻结状态下执行创建账号请求 post admin_accounts_path, params: { account: { name: "My company", subdomain: "example" } } # 直接比对到期时间是否等于冻结时间+30天,用be_within允许毫秒级误差避免数据库存储精度问题 expect(Account.first.trial_ends_at).to be_within(1.second).of(freeze_time + 30.days) end end
额外验证补充
如果需要同时验证到期后状态逻辑,可额外补充以下测试用例:
it "expires trial after exactly 30 days" do freeze_time = Time.current account = nil Timecop.freeze(freeze_time) do post admin_accounts_path, params: { account: { name: "My company", subdomain: "example" } } account = Account.first # 验证30天到期前仍在试用期 expect(account.on_generic_trial?).to be_truthy end # 跳到30天零1秒后验证试用期已结束 Timecop.freeze(freeze_time + 30.days + 1.second) do expect(account.on_generic_trial?).to be_falsey end end
内容的提问来源于stack exchange,提问作者abeidahmed
相关产品推荐
相关产品推荐

