Ruby on rails 如何使枚举字段类型为-Mongoid的模型通过规范测试

Ruby on rails 如何使枚举字段类型为-Mongoid的模型通过规范测试,ruby-on-rails,ruby-on-rails-4,rspec3,mongoid4,Ruby On Rails,Ruby On Rails 4,Rspec3,Mongoid4,EDIT:根据@max的建议,我将我的模型改为使用enum,但是我无法测试它的默认状态: it { is_expected.to validate_inclusion_of(:status).to_allow("draft", "published") } 可以在模型中使用以下代码: validates :status, :inclusion => { :in => ["draft", "published"] } 但这一部分仍然失败: it { is_expect

EDIT:根据@max的建议,我将我的模型改为使用enum,但是我无法测试它的默认状态:

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_预期。应该有_字段(:published.),属于_类型(布尔)。默认值为(false)}
预期Post中的字段名为“published”,类型为布尔,默认值为false,而得到的字段名为“published”,类型为Mongoid::Boolean

注意:我也尝试过:

field :published,         type: Boolean,     default: false
并在我的模型中添加了以下方法:

after_initialize :set_published, :if => :new_record?
然后

但似乎什么都不管用。我错过了什么

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个交换机是很棘手的-一个很棒的解决方案是使用枚举

首先编写规范:

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
然后添加到您的文件中

最后添加枚举字段:

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

如果我理解正确,您在模型中尝试了
Mongoid::Boolean
Boolean
,但在测试中没有尝试

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

it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }
(和
字段:published,类型:Mongoid::Boolean,默认值:false,在模型中)

第二个问题

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

没有视图的代码,我们无法帮助您

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

我不熟悉Rspec和您使用的语法,但它应该是这样的(假设您的模型名为
Post
):


Shoulda matchers有一个
it{should define_enum_for:status}
matcher for ActiveRecord enum,但我不知道Mongoid是否存在类似的匹配器。我明白你的意思,并已将代码更改为使用enum。谢谢你的建议!唯一的问题是我找不到如何测试它的默认状态上面的测试测试默认状态是草稿。你也可以做一些类似于
expect(Article.new.draft?).to-truthy
的事情来避免显式使用subject。这就成功了(
it{expect(Article.new.draft?)。to-truthy}
)谢谢!嘿@vmarquet,你的答案是正确的,但是max的建议似乎更有意义。无论如何,谢谢你的帮助!我没有意识到,没有。我只需要测试属性为“已发布”
的模型是否具有默认值“草稿”。我该怎么做呢?PS:我还是Rspec和TDD的新手。谢谢我已经更新了我的答案。
it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }
before {
    @post = Post.new
    # some initialization code if needed
    @post.save
}
expect(@post.published).to be("draft")