Подделка активной записи модели без БД - PullRequest
5 голосов
/ 28 сентября 2011

Мне кажется, что я что-то упустил. Я пишу рубиновый гем, который позволяет взаимодействовать с активной записью как дополнение к ее основной функции.

При написании тестовых примеров для этого мне нужно иметь возможность указать фиктивные модели активных записей для проверки этой функциональности. Было бы замечательно, если бы я мог получить экземпляр модели активной записи, который не нуждался бы в каком-либо соединении с БД, который мог бы иметь отношения, все такое, но не требовал от меня настройки таблиц в базе данных. Я довольно новичок в тестировании, и за пределами тестирования рельсов я чертовски новичок, но кажется, что я должен быть в состоянии сделать что-то подобное довольно легко, но я ничего не нахожу.

Может кто-нибудь сказать мне, что мне не хватает? Я смотрел на фабрики, производителей, светильники, все те, кто, кажется, хочет попасть в БД. Как люди тестируют драгоценные камни, где вам нужен объект AR только для тестирования?

Ответы [ 4 ]

9 голосов
/ 29 сентября 2011

Похоже, вам нужно NullDB :

NullDB - это шаблон Null Object, применяемый к адаптерам базы данных ActiveRecord. Это серверная часть базы данных, которая переводит взаимодействия с базой данных в no-ops. Использование NullDB позволяет вам тестировать бизнес-логику модели - включая ловушки after_save - даже не касаясь реальной базы данных.

2 голосов
/ 28 сентября 2011

Да, я хотел сделать это некоторое время назад в Rails 2.3, и это была огромная насмешливая головная боль.Я думаю, что теперь стало проще с ActiveModel, который дает вам явный интерфейс, если вы хотите свернуть свой собственный.

Кроме того, я не использовал его сам, но у Джоша Сусера есть драгоценный камень, который позволяет вам смешиватьAR-поведение в любом классе.Это похоже на использование простых объектов ruby ​​в формах, но, вероятно, также полезно для модульного тестирования.См. неформальный .

Он говорит об этом в недавнем эпизоде ​​ Ruby Rogues

2 голосов
/ 28 сентября 2011

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

Или используйте библиотеку замены дляAR, который обеспечивает тот же интерфейс, но не требует БД.Некоторое время я не пользовался рельсами, но некоторые были доступны.Это не совсем без тех же проблем, что и при использовании БД в первую очередь, так как к этим библиотекам обычно предъявляются другие требования (например, веб-службы, LDAP, ...), или просто требуется такая же настройка одиночной записи, как и с mocks.

Или укусите его и просто используйте приспособления, но сделайте их стоимость очень маленькой, используя sqlite DB в памяти только для тестов и правильных миграций.

1 голос
/ 20 сентября 2012

Другой вариант - использовать адаптер sqlite3 и запустить базу данных в памяти, а также использовать DatabaseCleaner, чтобы избавиться от записей после теста.

У этого подхода есть определенные преимущества:

  • Вы можете увидеть SQL в тесте, который упрощает процесс оптимизации запросов
  • Это близко к "реальным" примерам

С другой стороны, я должен сказать этоэто немного грязно, потому что это немного долго, но не стесняйтесь реструктурировать его;)

Вот краткое описание, что вам нужно для этого:

# in Gemfile
gem "activerecord" #since you are dealing with activerecord
gem "database_cleaner", :group => :test
gem "sqlite3", :group => :test

Я используюследующий подход, чтобы сохранить вещь, но вы можете иметь ее по-другому:

# in RAILS_ROOT/test/support/active_record.rb
require 'logger'

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3", :database => ':memory:'
)

#this line will print the SQL queries right into console 
ActiveRecord::Base.logger = Logger.new(STDOUT)

# in RAILS_ROOT/test/support/database_cleaner.rb
require 'database_cleaner'
DatabaseCleaner.strategy = :truncation
# or DatabaseCleaner.strategy = :trunsaction (it is up to you)

module OrmSetup
  def before_setup
    DatabaseCleaner.start
  end

  def after_teardown
    DatabaseCleaner.clean
  end
end

# in RAILS_ROOT/test/test_helper.rb
...
require File.expand_path("support/active_record", File.dirname(__FILE__))
require File.expand_path("support/database_cleaner", File.dirname(__FILE__))

class Test::Unit::TestCase
  include OrmSetup
end

И теперь в вашем тесте вы можете получить что-то вроде

require 'test_helper'

class User < ActiveRecord::Base
end

class MyFancyTest < Test::Unit::TestCase
  def setup
    before_setup
  end

  def teardown
    after_teardown
  end
end
...