Подтвердить что ты не робот

Как RSpec использовать общий модуль ActiveRecord без соответствующей таблицы базы данных?

Использование RSpec 2.6/Rails 3.1/Postgres:

Я пишу поддерживающий модуль (в моем lib/), который может включать любую AR-модель. Я бы хотел написать спецификацию для этого модуля. Он должен быть включен в модель AR:: Base, поскольку он загружает ассоциации при включении и использует некоторые методы AR, но я не хочу использовать существующую модель при написании rspec для этого модуля.

Я просто хотел бы создать произвольную AR-модель, но, очевидно, у нее не было бы таблицы, связанной в базе данных, и AR умирает. Вот kindda, что я хочу сделать:

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 относительно отношения, которое не существует.

Спасибо за вашу помощь!

4b9b3361

Ответ 1

Существует альтернативный способ решения этой проблемы с помощью rpsecs shared_examples_for, я упоминаю несколько трюков в фрагменте кода, но для получения дополнительной информации см. этот relishapp-rspec -руководство.

С этим вы можете протестировать свой модуль в любом из классов, которые его включают. Итак, вы действительно тестируете, что используете в своем приложении.

Посмотрим на пример:

# 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

Теперь создадим спецификацию для нашего модуля: movable_spec.rb

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

Ответ 2

Я столкнулся с подобной проблемой, и после долгих поисковых запросов я решил только настроить и снести таблицы в тестах RSpec. Вот фрагмент, который я использовал:

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

Я не в восторге от этого решения, но он работает. Надеюсь, что это поможет кому-то! Либо это, либо вдохновляет их опубликовать лучший способ выполнить это.

:)

Ответ 3

Вы можете переименовать self.columns

class Tableless < ActiveRecord::Base
  def self.columns
    @columns ||= [];
  end
end

то вы можете создать новый экземпляр reguralry

let(:dummy_instance) { Tableless.new }
it { is_expected.to be_valid}

Ответ 4

goggin13, спасибо за ваш ответ. В основном это работало для меня, за исключением того, что мне пришлось изменить методы экземпляра миграции на класс. то есть:.

С

 m = ActiveRecord::Migration.new
 m.verbose = false  
 m.create_table ...

Для

 m = ActiveRecord::Migration
 m.verbose = false  
 m.create_table ...

Ответ 5

Здесь небольшая вариация ответа goggin13, которая исправляет миграцию (как заметил Zac) и исправляет имя таблицы:

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