【问题标题】:How to get a spec test passing for model with enum field type - Mongoid如何让具有枚举字段类型的模型通过规范测试 - Mongoid
【发布时间】:2015-07-08 16:32:00
【问题描述】:

编辑:根据@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

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

【问题讨论】:

  • 我已经更新了我的答案。

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


【解决方案1】:

如果我理解正确,您在模型中尝试了 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")

【讨论】:

  • 嘿@vmarquet,您的回答是正确的,但最大建议似乎更有意义。无论如何感谢您的帮助!
  • 我不知道,不。我只需要测试属性published 的模型是否具有draft 的默认值。我该怎么做呢? PS:我还是 Rspec 和 TDD 的新手。谢谢!
【解决方案2】:
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 个开关很麻烦 - 一个很棒的解决方案是使用 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

【讨论】:

  • Should-matchers 有一个用于 ActiveRecord 枚举的 it { should define_enum_for :status } 匹配器,但我不知道 Mongoid 是否存在类似的匹配器。
  • 我明白你的意思,并已将代码更改为使用枚举。感谢您的建议!唯一的问题是我找不到如何测试它的默认状态
  • 上面的测试测试默认状态是draft。您还可以执行expect(Article.new.draft?).to be_truthy 之类的操作来避免明确使用主题。
  • 成功了 (it { expect(Article.new.draft?).to be_truthy }) 谢谢!
猜你喜欢
  • 2010-11-11
  • 2021-12-22
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多