Rspec 的哈希时间戳问题
Trouble with Rspec for timestamp in hashes
为了与哈希数据进行比较,我们在规范中使用了这个
it 'should return the rec_1 in page format' do
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
Presenter 是一个 class,它将接受 ActiveRecordObject 并以特定格式的哈希数据进行响应。
然后我们将带有时间戳的 updated_at 添加到 hash_data。
在我的代码中我有 updated_at = Time.zone.now
所以规范开始失败,因为 updated_at 有几秒的差异。
已尝试存根 Time.zone
it 'should return the rec_1 in page format' do
allow(Time.zone).to receive(:now).and_return('hello')
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
但现在 response_body_json.updated_at 变成了 'hello'
但右侧仍然带有时间戳
我哪里错了???
或者有没有其他更好的方法来处理这种情况?
由于您没有说明 response_body_json
和 Presenter#page
是如何定义的,我无法真正回答为什么您当前的尝试不起作用。
但是,我可以说我会使用不同的方法。
有两种编写测试的标准方法:
- 冻结时间.
假设您使用的是相对最新的 rails 版本,您可以在测试中的某处使用 use ActiveSupport::Testing::TimeHelpers#freeze_time
,例如类似于:
around do |example|
freeze_time { example.run }
end
it 'should return the movie_1 in page format' do
expect(response_body_json).to eql(Presenter.new(ActiveRecordObject).page)
end
如果您使用的是旧 rails 版本,您可能需要改用 travel_to(Time.zone.now)
。
如果您使用的是非常旧的 rails 版本(或非 rails 项目!),没有此帮助程序库,您可以使用 timecop
相反。
- 对时间戳使用模糊匹配器(例如
be_within
)。大致如下:
.
it 'should return the movie_1 in page format' do
expected_json = Presenter.new(ActiveRecordObject).page
expect(response_body_json).to match(
expected_json.merge(updated_at: be_within(3.seconds).of(Time.zone.now))
)
end
before do
movie_1.publish
allow(Time.zone).to receive(:now).and_return(Time.now)
get :show, format: :json, params: { id: movie_1.uuid }
end
it 'should return the rec_1 in page format' do
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
结束
以上代码解决了我的问题。
看来我把这个 allow(Time.zone).to receive(:now).and_return('hello')
放错地方了。它应该放在 before 块中,以便在测试用例 运行 之前设置它,我想它也可能必须在 get 请求之前设置。
不过 Tom Lord 的方法是更好的方法。
为了与哈希数据进行比较,我们在规范中使用了这个
it 'should return the rec_1 in page format' do
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
Presenter 是一个 class,它将接受 ActiveRecordObject 并以特定格式的哈希数据进行响应。
然后我们将带有时间戳的 updated_at 添加到 hash_data。
在我的代码中我有 updated_at = Time.zone.now
所以规范开始失败,因为 updated_at 有几秒的差异。
已尝试存根 Time.zone
it 'should return the rec_1 in page format' do
allow(Time.zone).to receive(:now).and_return('hello')
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
但现在 response_body_json.updated_at 变成了 'hello' 但右侧仍然带有时间戳
我哪里错了??? 或者有没有其他更好的方法来处理这种情况?
由于您没有说明 response_body_json
和 Presenter#page
是如何定义的,我无法真正回答为什么您当前的尝试不起作用。
但是,我可以说我会使用不同的方法。
有两种编写测试的标准方法:
- 冻结时间.
假设您使用的是相对最新的 rails 版本,您可以在测试中的某处使用 use ActiveSupport::Testing::TimeHelpers#freeze_time
,例如类似于:
around do |example|
freeze_time { example.run }
end
it 'should return the movie_1 in page format' do
expect(response_body_json).to eql(Presenter.new(ActiveRecordObject).page)
end
如果您使用的是旧 rails 版本,您可能需要改用 travel_to(Time.zone.now)
。
如果您使用的是非常旧的 rails 版本(或非 rails 项目!),没有此帮助程序库,您可以使用 timecop
相反。
- 对时间戳使用模糊匹配器(例如
be_within
)。大致如下:
.
it 'should return the movie_1 in page format' do
expected_json = Presenter.new(ActiveRecordObject).page
expect(response_body_json).to match(
expected_json.merge(updated_at: be_within(3.seconds).of(Time.zone.now))
)
end
before do
movie_1.publish
allow(Time.zone).to receive(:now).and_return(Time.now)
get :show, format: :json, params: { id: movie_1.uuid }
end
it 'should return the rec_1 in page format' do
expect(response_body_json).to eql(Preseneter.new(ActiveRecordObject).page)
end
结束
以上代码解决了我的问题。
看来我把这个 allow(Time.zone).to receive(:now).and_return('hello')
放错地方了。它应该放在 before 块中,以便在测试用例 运行 之前设置它,我想它也可能必须在 get 请求之前设置。
不过 Tom Lord 的方法是更好的方法。