【问题标题】:Rails 5 scaffold and Rspec testing for an enum in Controller testRails 5 脚手架和 Rspec 测试控制器测试中的枚举
【发布时间】:2017-03-02 22:58:14
【问题描述】:

我刚刚构建了一个 Rails 5 新应用程序 --api。我搭建了一个模型并添加了一个枚举。

class Track < ApplicationRecord
  enum surface_type: [:asphalt, :gravel, :snow], _prefix: true
end

其中一个脚手架控制器测试如下所示:

context "with invalid params" do
  it "assigns a newly created but unsaved track as @track" do
    post :create, params: {track: invalid_attributes}, session: valid_session
    expect(assigns(:track)).to be_a_new(Track)
  end
end

我在顶部添加了无效属性:

  let(:invalid_attributes) {{
    "name": "Brands Hatch",
    "surface_type": "wood"
  }}

并将期望行更改为此

expect(assigns(:track)).not_to be_valid

但测试不起作用,因为如果您传递无效的枚举,则无法创建 Track 对象。

控制器动作:

  def create
    @track = Track.new(track_params)

    if @track.save
      render json: @track, status: :created
    else
      render json: @track.errors, status: :unprocessable_entity
    end
  end

那么我该如何测试这个场景呢?

【问题讨论】:

  • 不可能create 对象,但您可以实例化它...使用.new,然后使用#update_attributes(或#assign_attributes#save)。你能展示你的控制器创建代码吗?
  • 谢谢,我添加了控制器代码。我猜想编写脚手架测试的人都没有考虑过这种极端情况。
  • 我不知道如何解释我的意思 - 但脚手架测试设置为使用“有效”和“无效”属性......这里的含义是为了测试验证(如 validates_presence_of)。枚举不使用 validates_presence_of,所以这就是我称之为边缘情况的原因。我想我必须写一些其他类型的测试,但我不确定是什么,叹息。 :(
  • 我刚读到这个stackoverflow.com/questions/29198307/…,似乎没有FactoryGirl这个测试是不可能的。在模型上调用“new”后,会立即检查枚举以查看它是否存在于枚举声明中。所以看起来枚举与模型验证的工作方式不同。

标签: ruby-on-rails rspec enums


【解决方案1】:

通过正常验证捕获无效:surface_type 的一种方法是拦截分配。

class Track < ApplicationRecord
  enum surface_type: [:asphalt, :gravel, :snow], _prefix: true
  attr_accessor :bad_surface_type
  validate :check_surface_type

  def surface_type=(surface)
    super surface
  rescue
    self.bad_surface_type = surface
    super nil
  end

  private

  def check_surface_type
    errors.add(:surface_type, "the value #{bad_surface_type} is not valid") if bad_surface_type
  end
end

【讨论】:

  • 确实很聪明。我刚刚发现这个问题表明这是在 Github stackoverflow.com/questions/37177893/… 上作为 Rails 上的一个问题提出的,并且阅读该问题后我发现枚举的推荐使用是跟踪内部应用程序状态....不要将它们暴露在应用程序之外。天哪,这对我来说是个新闻!
  • 嗯。对我来说也是新闻。我不需要担心这一点,因为我的枚举暴露给用户选择的地方我使用f.select 并控制呈现给最终用户的选项。所以我从来没有觉得需要测试无效的选项。
  • 是的,这就是引发异常而不是验证错误的原因。永远不可能设置无效值。除非您正在构建 API,否则客户端可能会发送无效值。所以我可能会将枚举转换为模型,从长远来看更容易维护。
猜你喜欢
  • 2017-01-04
  • 1970-01-01
  • 1970-01-01
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多