测试使用ActiveRecord的问题/模块
场景我提取了一个名为Taggable
。 它是一个允许任何模型支持标记的模块。 我已将此问题/模块包含在User
, Location
, Location
, Projects
。
我想为这个模块编写测试,但不知道从哪里开始。
题
1.我可以对Taggable
问题进行隔离测试吗?
在下面的示例中,测试失败,因为测试正在查找dummy_class table
。 我假设它正在这样做是因为Taggable
中的has_many
代码,因此它希望'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
那样足够的测试。 但我一直在读,你应该单独测试模块。
寻找关于正确方法的一些指导/策略。
我建议将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交互以测试关联之类的事情,因此您可能需要在测试期间在DB中创建临时表。 临时Ruby gem可能能够提供帮助,因为它旨在创建临时ActiveRecord模型及其底层数据库表。
Temping允许您创建由临时SQL表支持的任意ActiveRecord模型,以便在测试中使用。 如果您正在测试一个混合到ActiveReord模型中的模块而不转发具体类,则可能需要执行此类操作。
我使用ActiveRecord Tableless而不是Temping gem,这似乎有点过时了。
我设置的测试与Stuart M在答案中完全相同,但包括了我的DummyClass中所需的has_no_table
辅助方法和列。
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
关联,所以它仍然可能对你想要测试的内容没有帮助。
这是我的类似问题的解决方案:
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 mock_model
)被提取到rspec 3.0中的rspec-activemodel-mocks 。
此外,您还需要使用shoulda-matcher进行关联匹配。
正如在@StuartM的回答中所建议的,使用临时gem对我有用:
# test.rb/spec.rb Temping.create :dummy_class do include Taggable end describe Taggable do before do @dummy = DummyClass.new end ... end
- 访问ActiveSupport :: LogSubscriber子类中的Rails请求
- NoMethodError:ActiveSupport的未定义方法`halt_callback_chains_on_return_false =’:模块
- 如何从过时的TZInfo标识符中获取Rails TimeZone名称?
- 无法使用cache_classes = true为Concern(ActiveSupport :: Concern :: MultipleIncludedBlocks)定义多个“包含”块
- 两个ActiveSupport :: TimeWithZone对象之间的比较失败
- 如何使用Active Support核心扩展?
- Activesupport / Multi json:“无法识别您的适配器规范”
- 将Date对象转换为TimeWithZone
- 测试ActiveSupport :: TimeWithZone对象是否相等