Как я могу высмеять супер в ruby ​​с помощью rspec?

Я расширяю существующую библиотеку, создавая дочерний класс, который распространяется на класс библиотеки.

В дочернем классе я смог проверить большинство функций в методе initialize, но не смог высмеять вызов super. Детский класс выглядит примерно так.

class Child < SomeLibrary
    def initialize(arg)
        validate_arg(arg)
        do_something
        super(arg)
    end

    def validate_arg(arg)
        # do the validation
    end

    def do_something
        @setup = true
    end
end

Как я могу написать rspec test (с моккой), чтобы я мог высмеивать вызов super? Обратите внимание, что я тестирую функциональность метода initialize в классе Child. Должен ли я создавать отдельный путь кода, который не вызывает super, когда ему предоставляется дополнительный аргумент?

Ответы

Ответ 1

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

Вместо этого выясните, какое поведение этого класса изменится, если отсутствует вызов super, и напишите пример, который выполняет и проверяет это поведение.

Ответ 2

Хорошим способом проверить это является ожидание некоторых действий, предпринятых суперклассом - пример:

class Some::Thing < Some
 def instance_method
    super
 end
end

и суперкласс:

class Some
  def instance_method
     another_method
  end

  def self.another_method # not private!
     'does a thing'
  end
end

теперь тест:

 describe '#instance_method' do 
    it 'appropriately triggers the super class method' do
      sawm = Some::Thing.new
      expect(sawm).to receive(:another_method)
      sawm.instance_method
    end
 end

Все это определяет, что супер был вызван над суперклассом

Эта полезность шаблона зависит от того, как вы структурируете свои тесты/какие ожидания у вас есть мутации типа "ребенок/производный" с помощью применяемого метода super.

Кроме того, обратите внимание на методы class и instance, вам нужно будет отрегулировать allows и expects соответственно

YMMV

Ответ 3

Немного опоздал на эту вечеринку, но вы также можете отказаться от использования ключевого слова super и вместо этого сделать

class Parent
  def m(*args)
  end
end

class Child < Parent
  alias super_m m

  def m(*args)
    super_m(*args)
  end
end

Таким образом, ваш супер метод доступен, как и любой другой метод, и может, например, быть заколотым как любой другой метод. Основным недостатком является то, что вы должны явно передавать аргументы для вызова метода super.