Как протестировать модуль, расширяющий ActiveSupport::Concern?

У меня есть модуль, расширяющий ActiveSupport::Concern. Вот блок included:

included do
  after_save :save_tags

  has_many :taggings, :as => :taggable
  has_many :tags, :through => :taggings
end

Как я могу заглушить эти звонки? Я пробовал несколько способов, но Ruby жалуется, что эти методы не существуют, когда я пытаюсь протестировать модуль изолированно.

Спасибо!


person Fire Emblem    schedule 31.05.2011    source источник
comment
Я думаю, вы можете посмотреть мой ответ на аналогичную проблему stackoverflow.com/questions/15868210/   -  person freemanoid    schedule 28.10.2014


Ответы (2)


Я думаю, у вас есть несколько вариантов, в зависимости от того, что вы хотите протестировать.

Если вы просто хотите проверить, действительно ли модуль устанавливает ассоциации has_many и обратный вызов after_save, вы можете настроить простое ожидание rspec:

class Dummy
end

describe Taggable do
  it "should setup active record associations when included into models" do
    Dummy.should_receive(:has_many).twice
    Dummy.should_receive(:after_save).with(:save_tags)
    Dummy.send(:include, Taggable) # send is necessary because it's a private method
  end
end

Вы, вероятно, можете довольно легко протестировать метод save_tags без дальнейших насмешек, но если вы хотите протестировать поведение, которое зависит от установленных ассоциаций has_many, вы можете создать еще один класс-пустышку с заглушками has_many и after_save, но с аксессорами для ассоциаций:

class Dummy
  attr_accessor :taggings, :tags

  # stub out these two
  def self.has_many
  end

  def self.after_save
  end

  def initialize
    @taggings = []
    @tags = []
  end

  include Taggable
end

describe Taggable do
  it "should provide a formatted list of tags, or something" do
     d = Dummy.new
     d.tags = [double('tag')]
     d.formatted_tags.size.should == 1
  end
end

Мы можем очистить этот (несколько хрупкий тестовый класс) с помощью небольшого количества метапрограммирования, хотя на ваше усмотрение, сделает ли это тест слишком сложным для понимания.

class Dummy
  def self.has_many(plural_object_name, options={})
    instance_var_sym = "@#{plural_object_name}".to_sym

    # Create the attr_reader, setting the instance var if it doesn't exist already
    define_method(plural_object_name) do
      instance_variable_get(instance_var_sym) ||
          instance_variable_set(instance_var_sym, [])
    end

    # Create the attr_writer
    define_method("#{plural_object_name}=") do |val|
      instance_variable_set(instance_var_sym, val)
    end
  end

  include Taskable
end
person Dhruv    schedule 20.12.2012

Перед началом теста вам необходимо убедиться, что вы сначала загрузили файл с исходным определением ActiveSupport::Concern, а после этой загрузки вы должны загрузить свое расширение. Обязательно загрузите правильные файлы, так как механизм автозагрузки rails найдет ваше расширение в пользу оригинала.

person moritz    schedule 31.05.2011
comment
Так что я на самом деле должен использовать реальную заботу здесь? Как я могу создать фиктивную проблему? - person Fire Emblem; 01.06.2011