RSpec和Factory Girl - datetime字段出现错误

3

我有一个问题:

环境:Ruby: 2.3.1 和 Rails 5.0.0.1

我试图使用 RSpec 和 Factory Girl 验证日期时间字段。

我收到了以下错误:

expected: "2016-11-11 13:30:31 UTC"  (From Factory Girl)
     got: "2016-11-11T13:30:31.218Z" (From database)

我的代码:

klass_object = FactoryGirl.create(:character)
klass = Character


RSpec.shared_examples 'API GET #index' do |klass|
  before { get :index, params: params, accept: Mime[:json] }


  it "returns a list of #{klass.to_s.underscore.pluralize}" do
    object_array = json(response.body)

    klass_attributes = klass.attribute_names.without("id", "created_at", "updated_at").map(&:to_sym)

    klass_attributes.each do |attribute|
      object_array.each do |object|
        expect(object[attribute].to_s).to eq(klass_object[attribute].to_s)
      end
    end
  end
  ...
end

工厂:

FactoryGirl.define do
  factory :character do
    marvel_id { Faker::Number.number(6).to_i }
    name { Faker::Superhero.name }
    description { Faker::Hipster.paragraphs(1) }
    modified { Faker::Date.between(DateTime.now - 1, DateTime.now) }

    factory :invalid_character do
      id ''
      name ''
      marvel_id ''
      modified ''
    end
  end

结束

我该如何纠正这个问题?

我已经尝试了,它可以运行,但我认为它并不是很好。有更好的方法吗?

    object_array.each do |object|
      if ActiveSupport::TimeWithZone == klass_object[attribute].class
        expect(object[attribute].to_datetime.strftime("%Y-%m-%d %H:%M:%S")).to eq(klass_object[attribute].to_datetime.strftime("%Y-%m-%d %H:%M:%S"))
      else
        expect(object[attribute].to_s).to eq(klass_object[attribute].to_s)
      end
    end

感谢您的帮助。
3个回答

2

我建议您改变比较结果的方法。您可以使用基于黄金大师思想的方法。

根据这种方法,您可以拍摄对象的快照,然后将所有未来版本的对象与快照进行比较。

在您的情况下,您可以首先编写 json fixture,并检查 json 是否正确,然后再与结果 json 进行比较。

例如

approved.json

[
  {
    "travel_time_seconds": 43200,
    "available_seats_amount": 10,
    "departure_at": "2016-04-08T02:00:00.000+03:00",
    "arrival_at": "2016-04-08T17:00:00.000+03:00",
    "source_point_name": "New York",
    "destination_point_name": "Moscow",
    "tickets_count": 2
  }
]

controller_spec.rb

RSpec.shared_examples 'API GET #index' do |klass|
  before { get :index, params: params, accept: Mime[:json] }

  it "returns a list of #{klass.to_s.underscore.pluralize}" do
    verify(format: :json) { json(response.body).map {|o| o.except('id', 'created_at', 'updated_at' }
  end
  ...
end

例如,approvals gem可以帮助您实现这一点。

1
我知道这是一个非常老的问题,但我今天刚找到了解决方案,并且找不到其他答案。我一直在使用Faker,但是日期/时间格式似乎不能很好地与Ruby时间计算配合使用,需要进行大量的调整。
然而,如果您在工厂中使用Time,然后将其转换为.to_i,它将以正确的格式发送到数据库,以便在rspec中进行比较。
迁移:
class CreateExperiences < ActiveRecord::Migration[5.2]
  def change
    create_table :experiences do |t|
      t.datetime :start_date

工厂:

FactoryBot.define do
  when_it_started = Time.zone.now - rand(3000).days
  factory :experience do
    start_date { when_it_started.to_i }

规范:
RSpec.describe "Experiences API", type: :request do
  let!(:valid_attributes) { attributes_for(:experience) }
  describe "POST /v1/experiences" do
    before { post "/v1/experiences", params: valid_attributes }
      it "creates an experience" do
        expect(JSON.parse(response.body).except("id", "created_at", "updated_at")).to eq(valid_attributes.stringify_keys)
      end

然后我的测试通过了。希望这能帮助其他人!


0

尝试使用to_datetime而不是to_s

expect(object[attribute].to_datetime).to eq(klass_object[attribute].to_datetime)

在这种情况下,我正在循环遍历类中的每个属性。因此,并非所有属性都是日期时间类型。 - Kelvin Matheus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接