测试的担忧/模块使用的ActiveRecord(Testing a concern / module

2019-08-20 04:18发布

情景我已经提取了一个名为关注 Taggable 。 这是一个模块,允许任何模型来支持标记。 我已经包含了这种担忧/模块到像模特UserLocationPlacesProjects

我想写这个模块的测试,但不知道从哪里开始。


1.我可以做隔离测试上Taggable的关注?
在测试下面的例子,因为测试正在寻找失败dummy_class table 。 我假设它做的,因为这样has_many在代码中Taggable ,从而导致它预计'DummyClass'是一个ActiveRecord对象。

# /app/models/concerns/taggable.rb
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :taggings, :as => :taggable, :dependent=> :destroy
    has_many :tags, :through => :taggings
  end

  def tag(name)
    name.strip!
    tag = Tag.find_or_create_by_name(name)
    self.taggings.find_or_create_by_tag_id(tag.id)
  end
end


# /test/models/concerns/taggable_test.rb
require 'test_helpers'

class DummyClass
end

describe Taggable do
  before do
    @dummy = DummyClass.new
    @dummy.extend(Taggable)
  end

  it "gets all tags" do
    @dummy.tag("dummy tag")
    @dummy.tags.must_be_instance_of Array
  end
end

我的一部分想,如果我只是测试已经包括它里面这个模块像模特User这足够测试的。 但我继续阅读,你应该在隔离测试模块。

寻找在正确的方法是什么的一些指导/战略。

Answer 1:

我建议有DummyClass是通用ActiveRecord::Base孩子用很少的自定义代码除了刚才include Taggable ,这样你会被隔离您的关心模块尽可能多的,但仍然是一个AR类。 避免使用喜欢你的“真正的”类之一的User仍然在这些类中的任何其他代码,这似乎是有价值的隔离你。

因此,像这样:

class DummyClass < ActiveRecord::Base; end

describe Taggable do
  before do
    @dummy_class = DummyClass.new
  end
  ...
end

由于您的DummyClass可能需要实际与DB测试之类的社团互动,你可能需要在测试期间创建数据库临时表。 该临时工红宝石宝石也许能够帮助是,因为它的设计,创建临时的ActiveRecord模型和它们的底层数据库表。

临时工允许您创建通过在试验中使用的临时SQL表支持任意的ActiveRecord模型。 您可能需要,如果你正在测试,是为了混入ActiveReord车型没有中继上一个具体的类模块做这样的事情。



Answer 2:

我去使用ActiveRecord的无表 ,而不是在做临时工的宝石,这似乎是过时的时刻了一点出来。

我建立了我的测试了完全一样的司徒中号在他的答案 ,但包括has_no_table我DummyClass所需的辅助方法和列。

class DummyClass < ActiveRecord::Base
  # Use ActiveRecord tableless
  has_no_table
  # Add table columns
  column :name, :string
  # Add normal ActiveRecord validations etc
  validates :name, :presence => true
end   

这个工作对我需要测试,这是扩展模块什么ActiveRecord::Base有几个方法,但我还没有与任何尝试过has_many关联,以便它仍然可能无法与你想考什么帮助。



Answer 3:

这是我类似的问题的解决方案:

describe Taggable do
  subject { mock_model('User').send(:extend, Taggable) }

  it { should have_many(:tags) }
  ...

  describe "#tag" do
    ...
  end
end

事实上mock_model('User')可以模拟系统中的任何存在的模型。

这不是一个理想的解决方案,但至少它是明确和嘲笑一切。

注意mock_model (AR嘲笑)提取到rspec的-activemodel的-嘲笑在rspec的3.0。
另外你需要使用早该-匹配器的匹配器的关联。



Answer 4:

正如@ StuartM建议的答案 ,使用临时工宝石为我工作:

# test.rb/spec.rb
Temping.create :dummy_class do
  include Taggable
end

describe Taggable do
  before do
    @dummy = DummyClass.new
  end
  ...
end


文章来源: Testing a concern / module that uses ActiveRecord