Супер способ заглушки в контроллер


Как заглушить: супер метод из включенного модуля. У меня есть следующий контроллер:

class ImportsController < BaseController
   include ImportBackend

  def import_from_file
    super
  rescue TransferPreview::Error => exc
    flash[:error] = "Some String"
    redirect_to imports_path
  end
end

И модуль importBackend:

module ImportBackend
  def import_from_file
    //something
  end
end

Я хочу проверить этот контроллер. Мой вопрос заключается в том, как заглушить метод в ImportBackend, чтобы вызвать ошибку? Я попробовал пару решений, но ничего не работает:

ImportBackend.stub(:import_from_file).and_raise(Transfer::Error)
controller.stub(:super).and_raise(Transfer::Error)
controller.stub(:import_from_file).and_raise(Transfer::Error)

Спасибо за все ответы.

1 4

1 ответ:

В Ruby super выглядит как метод, но на самом деле это ключевое слово со специальным поведением (например, super и super() делают разные вещи, в отличие от любого другого метода Ruby), и вы не можете заглушить его.

Что вы действительно хотите сделать, так это заглушить метод, который вызывает super, который в данном случае является ImportBackend#import_from_file. Поскольку это микшер из модуля (а не суперкласса), вы не можете заглушить его обычным способом. Вы можете, однако, определить фиктивный модуль, который имеет макет поведения, которое вы хотите, и include он в вашем класс. Это работает потому, что когда несколько модулей определяют mixin, super вызовет последний включенный. Вы можете прочитать больше об этом подходе здесь. В вашем случае это выглядело бы примерно так:
mock_module = Module.new do
  def import_from_file
    raise Transfer::Error
  end
end

controller.singleton_class.send(:include, mock_module)

В зависимости от ваших других спецификаций, это может привести к некоторым осложнениям с teardown, но я надеюсь, что это поможет вам начать.