How to RSpec a shared ActiveRecord module without associated database table?
使用RSpec 2.6 / Rails 3.1 / Postgres:
我正在编写一个支持模块(在我的lib /中),任何AR模型都可以包含该模块。我想为此模块编写规格。它需要包含在AR :: Base模型中,因为当包含它时它会加载关联,并且依赖于某些AR方法,但是在为该模块编写rspec时我不想使用我现有的模型。
我只想创建一个任意的AR模型,但是很显然,它在数据库中没有关联的表,而AR正在消失。这是我想做的事情:
1 2 3 4 5 6 7 8 9 10 11 12 13 | class SomeRandomModel < ActiveRecord::Base include MyModule # simulate DB attributes that MyModule would be using attr_accessor :foo, :bar, :baz end describe SomeRandomModel do it '#some_method_in_my_module' do srm = SomeRandomModel.new(:foo => 1) srm.some_method_in_my_module.should eq(something) end end |
当然,我在postgres中遇到了关于该关系不存在的错误。
感谢您的帮助!
有一种使用rpsecs
使用此方法,您可以在包含该模块的任何类中测试您的模块。因此,您实际上正在测试您在应用程序中使用的功能。
让我们看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # Lets assume a Movable module module Movable def self.movable_class? true end def has_feets? true end end # Include Movable into Person and Animal class Person < ActiveRecord::Base include Movable end class Animal < ActiveRecord::Base include Movable end |
现在让我们为我们的模块创建规格:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | shared_examples_for Movable do context 'with an instance' do before(:each) do # described_class points on the class, if you need an instance of it: @obj = described_class.new # or you can use a parameter see below Animal test @obj = obj if obj.present? end it 'should have feets' do @obj.has_feets?.should be_true end end context 'class methods' do it 'should be a movable class' do described_class.movable_class?.should be_true end end end # Now list every model in your app to test them properly describe Person do it_behaves_like Movable end describe Animal do it_behaves_like Movable do let(:obj) { Animal.new({ :name => 'capybara' }) } end end |
我遇到了类似的问题,经过大量的搜索之后,我决定只在RSpec测试中设置和删除表。这是我一直在使用的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | describe"stuff you are testing do" do before :all do m = ActiveRecord::Migration.new m.verbose = false m.create_table :random_class do |t| t.string :field_1 t.integer :field_2 end end after :all do m = ActiveRecord::Migration.new m.verbose = false m.drop_table :random_class end class RandomClass < ActiveRecord::Base attr_accessible :field_1, :field_2 end # Your regular RSpec before(:each) blocks and tests # ... # e.g. it"should be able to use RandomClass" do rc = RandomClass.create! :field_1 =>"hello", :field_2 => 5 rc.field_1.should =="hello" rc.field_2.should == 5 end end |
我不喜欢这种解决方案,但是它有效。希望这对某人有帮助!要么激励他们发布实现此目标的最佳方法。
:)
您可以覆盖
1 2 3 4 5 | class Tableless < ActiveRecord::Base def self.columns @columns ||= []; end end |
然后您可以创建一个新的实例法规
1 2 | let(:dummy_instance) { Tableless.new } it { is_expected.to be_valid} |
这与goggin13的答案略有不同,它可以解决迁移问题(如Zac所述)并修复表名:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | describe"stuff you are testing do" do before :all do m = ActiveRecord::Migration m.verbose = false m.create_table :random_classes do |t| t.string :field_1 t.integer :field_2 end end after :all do m = ActiveRecord::Migration m.verbose = false m.drop_table :random_classes end class RandomClass < ActiveRecord::Base attr_accessible :field_1, :field_2 end # Your regular RSpec before(:each) blocks and tests # ... # e.g. it"should be able to use RandomClass" do rc = RandomClass.create! :field_1 =>"hello", :field_2 => 5 rc.field_1.should =="hello" rc.field_2.should == 5 end end |
goggin13,谢谢您的回答。它对我最有用,除了我必须将迁移实例方法更改为类方法。即:
来自
1 2 3 | m = ActiveRecord::Migration.new m.verbose = false m.create_table ... |
致
1 2 3 | m = ActiveRecord::Migration m.verbose = false m.create_table ... |