Как RSpec совместно используемый модуль ActiveRecord без связанной таблицы базы данных? - PullRequest
14 голосов
/ 06 октября 2011

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

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

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

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 я получаю сообщение об отсутствии связи.

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

Ответы [ 5 ]

16 голосов
/ 02 августа 2013

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

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

Давайте рассмотрим пример:

# 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
15 голосов
/ 16 мая 2012

Я столкнулся с подобной проблемой, и после долгих поисков я остановился на настройке и разборке таблиц в моих тестах 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

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

:)

2 голосов
/ 30 марта 2016

Вы можете перезаписать self.columns

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

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

let(:dummy_instance) { Tableless.new }
it { is_expected.to be_valid}
0 голосов
/ 13 июня 2013

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

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
0 голосов
/ 09 мая 2013

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

С

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

К

 m = ActiveRecord::Migration
 m.verbose = false  
 m.create_table ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...