鉴于我对Personable
具有方法的 Rails 4 应用程序有疑虑,我full_name
将如何使用 RSpec 进行测试?
关注/personable.rb
module Personable
extend ActiveSupport::Concern
def full_name
"#{first_name} #{last_name}"
end
end
鉴于我对Personable
具有方法的 Rails 4 应用程序有疑虑,我full_name
将如何使用 RSpec 进行测试?
关注/personable.rb
module Personable
extend ActiveSupport::Concern
def full_name
"#{first_name} #{last_name}"
end
end
您找到的方法肯定可以测试一些功能,但看起来很脆弱 - 您的虚拟类(实际上只是Struct
您的解决方案中的一个)可能会或可能不会像include
您关心的真实类一样表现。此外,如果您尝试测试模型问题,您将无法执行诸如测试对象的有效性或调用 ActiveRecord 回调之类的操作,除非您相应地设置数据库(因为您的虚拟类没有数据库表支持它)。此外,您不仅要测试关注点,还要测试关注点在模型规范中的行为。
那么为什么不一石两鸟呢?通过使用 RSpec 的共享示例组,您可以针对使用它们的实际类(例如模型)测试您的关注点,并且您将能够在使用它们的任何地方测试它们。而且您只需编写一次测试,然后将它们包含在任何使用您关注的模型规范中。在您的情况下,这可能看起来像这样:
# 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'
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 对象之外的任何事情都不会做。
为了回应我收到的评论,这就是我最终做的事情(如果有人有改进,请随时发布):
规范/关注/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
另一个想法是使用with_model gem来测试这样的事情。我正在寻找自己测试一个问题,并看到pg_search gem 这样做。这似乎比在单个模型上进行测试要好得多,因为这些可能会发生变化,并且在规范中定义您将需要的东西很好。
以下对我有用。就我而言,我担心的是调用生成的 * _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
只需在规范中包含您的关注并测试它是否返回正确的值。
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