ruby-on-rails 如何在Rails中测试关注点

iq0todco  于 12个月前  发布在  Ruby
关注(0)|答案(5)|浏览(101)

假设我在Rails 4应用程序中有一个Personable关注点,它有一个full_name方法,我该如何使用RSpec测试它?

concerns/personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

字符串

oknrviil

oknrviil1#

您找到的方法当然可以测试一点功能,但似乎相当脆弱-您的伪类(实际上只是解决方案中的一个Struct)可能会也可能不会像include所关注的真实的类一样行为。另外,如果您试图测试模型关注点,除非相应地设置数据库,否则无法执行诸如测试对象的有效性或调用ActiveRecord回调之类的操作此外,您不仅要测试关注点,还要测试关注点在模型规范中的行为。
那么为什么不一石二鸟呢?通过使用RSpec的shared example groups,您可以针对使用它们的实际类(例如,模型)* 测试您的关注点,并且 * 您将能够在使用它们的任何地方测试它们。您只需编写一次测试,然后将它们包含在使用您关注点的任何模型规范中。在您的情况下,这可能看起来像这样:

# app/models/concerns/personable.rb
module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb
require 'spec_helper'

RSpec.shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb
require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb
require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

字符串
当您开始在关注点中做一些事情(比如调用AR回调)时,这种方法的优势变得更加明显,在这种情况下,任何小于AR对象的东西都无法使用。

3pmvbmvn

3pmvbmvn2#

作为对我收到的评论的回应,以下是我最终所做的 (如果有人有改进,请随时发布)

spec/concerns/personable_spec.rb

require 'spec_helper'

describe Personable do
  let(:test_class) { Struct.new(:first_name, :last_name) { include Personable } }
  let(:personable) { test_class.new("Stewart", "Home") }

  it "has a full_name" do
    expect(personable.full_name).to eq("#{personable.first_name} #{personable.last_name}")
  end
end

字符串

qjp7pelc

qjp7pelc3#

另一个想法是使用with_model gem来测试这样的东西。我想自己测试一个关注点,并看到了pg_search gem doing this。这似乎比在单个模型上测试要好得多,因为这些模型可能会改变,而且在规范中定义你需要的东西也很好。

63lcw9qa

63lcw9qa4#

下面的方法对我来说很有效。在我的例子中,我关心的是调用生成的**_path* 方法,而其他方法似乎不起作用。这种方法将给予你访问一些只在控制器上下文中可用的方法。

关注:

module MyConcern
  extend ActiveSupport::Concern

  def foo
    ...
  end
end

字符串

规格:

require 'rails_helper'

class MyConcernFakeController < ApplicationController
  include MyConcernFakeController
end

RSpec.describe MyConcernFakeController, type: :controller do    
  context 'foo' do
    it '' do
      expect(subject.foo).to eq(...)
    end
  end
end

jljoyd4f

jljoyd4f5#

只要在spec中包含您的关注点,并测试它是否返回正确的值。

RSpec.describe Personable do
  include Personable

  context 'test' do
    let!(:person) { create(:person) }

    it 'should match' do
       expect(person.full_name).to eql 'David King'
    end
  end
end

字符串

相关问题