如何使用枚举字段类型为模型传递规范测试 - Mongoid

时间:2015-07-08 16:32:00

标签: ruby-on-rails ruby-on-rails-4 rspec3 mongoid4

编辑:根据@max建议,我正在改变我的模型以使用枚举,但是我无法测试默认状态:

it { is_expected.to validate_inclusion_of(:status).to_allow("draft", "published") }

使用模型中的以下代码可以正常工作:

validates :status,        :inclusion => { :in => ["draft", "published"] }

但这部分仍然失败:

it { is_expected.to have_field(:status).with_default_value_of("draft") }

请注意我正在使用Mongoid。我的模型规格中有这个:

陈旧问题 - 保留供参考?

it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }

在我的模型中,我有这个:

field :published,         type: Mongoid::Boolean,     default: false

但是没有用。我尝试删除Mongoid位但得到同样的错误:

Failure/Error: it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) } Expected Post to have field named "published" of type Boolean with default value of false, got field "published" of type Mongoid::Boolean

注意:我也尝试过:

field :published,         type: Boolean,     default: false

并在我的模型中添加了以下方法:

after_initialize :set_published, :if => :new_record?

然后

private
def set_published
  self.published ||= false
end

但似乎没有任何效果。我错过了什么?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,您在模型中尝试了Mongoid::BooleanBoolean,但未在测试中尝试过。

鉴于测试失败消息,我认为它应该是:

it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }

(和模型中的field :published, type: Mongoid::Boolean, default: false

第二个问题

您是否知道have_field是对视图(生成的HTML)进行测试,而不是检查数据库中是否存在该字段?

如果没有您的观点代码,我们无法为您提供帮助。

要检查默认值是否为draft,我不知道任何内置的Rails测试方法,因此您应该手动完成。首先创建模型的新实例,保存它,然后检查发布的字段是否具有draft值。

我不熟悉Rspec和您正在使用的语法,但它应该类似(假设您的模型名为Post):

before {
    @post = Post.new
    # some initialization code if needed
    @post.save
}
expect(@post.published).to be("draft")

答案 1 :(得分:1)

class Article
  include Mongoid::Document
  field :published, type: Boolean, default: false
end

require 'rails_helper'

RSpec.describe Article, type: :model do
  it { is_expected.to have_field(:published)
                      .of_type(Mongoid::Boolean)
                      .with_default_value_of(false) }
end

mongoid (4.0.2)mongoid-rspec (2.1.0)上传递完全正常。

但坦率地说,将布尔值用于模型状态是次优的。

如果您考虑博客文章或文章,可以是:

 1. draft
 2. published
 3. deleted
 4. ... 

在模型中添加N个开关是icky - 一个很棒的解决方案是使用Enums。

首先编写规范:

RSpec.describe Article, type: :model do

  specify 'the default status of an article should be :draft' do
    expect(subject.status).to eq :draft
  end

  # or with rspec-its
  # its(:status) { should eq :draft }
end

然后将gem "mongoid-enum"添加到您的Gemfile中。

最后添加枚举字段:

class Article
  include Mongoid::Document
  include Mongoid::Enum
  enum :status, [:draft, :published]
end

枚举添加了所有这些令人敬畏的功能:

Article.published # Scope to get all published articles
article.published? # Interrogation methods for each state.
article.published! # sets the status