Rails testing: Thay đổi thời gian với TimeHelpers
Bài đăng này đã không được cập nhật trong 6 năm
Vấn đề
Hãy tưởng tượng bạn đang test ứng dụng Rails của mình với RSpec, bạn cần di chuyển thời gian đến tương lai hoặc quá khứ để test các chức năng của mình. Bạn biết rằng Timecop có đầy đủ những thứ bạn cần về thời gian nhưng bạn cũng mới nghe về 1 module được xây dựng sẵn từ Rails 4.1 tên ActiveSupport::Testing::TimeHelpers đáp ứng đầy đủ những thứ bạn cần. Bạn sẽ quyết định sẽ dùng gem Timecop hay sử dụng module kia?
Để có câu trả lời cho riêng mình, chúng ta hãy cũng tìm hiểu về module TimeHelpers nhé!
Các method của Timehelpers
travel(duration, &block)
Thay đổi thời gian hiện tại thành thời gian trong tương lai hoặc trong quá khứ bằng khoảng cách đến Time.now
, Date.today
và DateTime.now
Time.current # => Tue, 23 Jan 2018 22:13:47 JST +09:00
travel 1.day
Time.current # => Wed, 24 Jan 2018 22:14:20 JST +09:00
Date.current # => Wed, 24 Jan 2018
DateTime.current # => Wed, 24 Jan 2018 22:14:20 +0900
Phương thức này cũng chấp nhận một block, nó sẽ trả về thời gian ban đầu ở cuối block:
Time.current # => Wed, 24 Jan 2018 22:14:20 JST +09:00
travel 1.day do
User.create.created_at # => Wed, 24 Jan 2018 22:14:44 JST +09:00
end
Time.current # => Tue, 23 Jan 2018 22:17:28 JST +09:00
travel_back()
Trả về thời gian ban đầu bằng cách xóa các phần khai báo được thêm vào bởi
travel
và travel_to
Time.current # => Tue, 23 Jan 2018 22:18:10 JST +09:00
travel_to Time.zone.local(2015, 11, 24, 01, 04, 44)
Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00
travel_back
Time.current # => Tue, 23 Jan 2018 22:19:23 JST +09:00
travel_to(date_or_time)
Thay đổi thời gian hiện tại thành thời gian cho trước bằng cách bỏ
Time.now
, Date.today
và DateTime.now
để trả lại thời gian hoặc ngày được truyền vào phương thức này.
Time.current # => Tue, 23 Jan 2018 22:20:01 JST +09:00
travel_to Time.zone.local(2015, 11, 24, 01, 04, 44)
Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00
Date.current # => Tue, 24 Nov 2015
DateTime.current # => Tue, 24 Nov 2015 01:04:44 +0900
Ngày được lấy làm dấu thời gian là đầu ngày trong múi giờ của ứng dụng. Time.current
trả về dấu thời gian, và Time.now
tương đương của nó trong múi giờ hệ thống. Tương tự như vậy, Date.current
trả về một ngày bằng đối số, và Date.today
là ngày theo Time.now
. (Lưu ý rằng bạn hiếm khi phải xử lí Time.now
, hoặc Date.today
, để tôn trọng múi giờ của ứng dụng, hãy luôn sử dụng Time.current
và Date.current
.)
Phương thức này cũng chấp nhận một block, nó sẽ trả về thời gian ban đầu ở cuối block:
Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00
travel_to Time.zone.local(2015, 11, 24, 01, 04, 44) do
Time.current # => Tue, 24 Nov 2015 01:04:44 JST +09:00
end
Time.current # => Tue, 23 Jan 2018 22:27:42 JST +09:00
Ứng dụng trong Rspec
Tưởng tượng rằng bạn phải thống kê số like của người dùng trong ngày hôm qua, bạn viết RSpec như sau:
require "rails_helper"
describe "#create" do
before do
travel_to("2017-01-18 10:00:00")
user.like.create
end
context "when user liked" do
it "should create stats of today like" do
travel_to("2017-01-19 10:00:00")
expect(StatsOfLike.on_yesterday.size).to eq 1
end
end
end
Khi bạn chạy test của bạn, bạn nhận đc thông báo lỗi method_missing: undefined method travel_back for RSpec::ExampleGroups
. Làm thế nào để sửa lỗi này? Hãy include ActiveSupport::Testing::TimeHelpers
vào phần test của bạn.
require "rails_helper"
include ActiveSupport::Testing::TimeHelpers
describe "#create" do
before do
travel_to("2017-01-18 10:00:00")
user.like.create
end
context "when user liked" do
it "should create stats of today like" do
travel_to("2017-01-19 10:00:00")
expect(StatsOfLike.on_yesterday.size).to eq 1
end
end
end
Một cách khác để thêm module này vào:
RSpec.configure do |config|
....
config.include ActiveSupport::Testing::TimeHelpers
....
end
Vậy là mình đã hoàn thành bài giới thiệu về module TimeHelpers, chúc các bạn viết test dễ dàng hơn với module này!
All rights reserved