Невозможно вызвать метод экземпляра Ruby mixin из RSpec

#ruby #unit-testing #rspec #mixins #rspec3

#рубиновый #модульное тестирование #rspec #mixins #rspec3

Вопрос:

Цель:

Я хочу запустить базовый модульный тест RSpec для метода экземпляра mixin (модуля) с именем Debug. Ниже приведено содержимое файла Debug mixin:

Файл Mixin: ./mixins/debug.rb

 module Debug
  public
    def class_info?
      "#{self.class.name}"
    end
end
 

Проверка методов экземпляра Debug mixin, доступных из RSpec:

Когда я запускаю irb и включаю Debug mixin с помощью команд require_relative './mixins/debug.rb' и include Debug , а затем вызываю Debug.class_info? его, он успешно возвращает "Module"

Затем, если я выполню rspec следующий модульный тест RSpec, чтобы подтвердить, что контекст RSpec может получить доступ к методам экземпляра mixin, тест успешно пройден:

Настройка модульного тестирования RSpec # 1: ./spec/mixins/debug_spec.rb

 require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
  include Debug

  before(:each) do
    @class_info_instance_method = Debug.instance_methods[0].to_s
  end

  context "with mixins" do
    it "has class info instance method" do
      expect(@class_info_instance_method).to eq "class_info?"
    end
  end
end
 

Проблема при вызове метода экземпляра Debug mixin из RSpec:

Наконец, я изменяю модульный тест RSpec следующим образом, поэтому вместо этого он фактически вызывает метод class_info? экземпляра Debug mixin:

Настройка модульного тестирования RSpec # 2: ./spec/mixins/debug_spec.rb

 require_relative '../../mixins/debug.rb'

RSpec.describe Debug, "#class_info?" do
  include Debug

  before(:each) do
    @class_info = Debug.class_info?
  end

  context "with mixins" do
    it "shows class info" do
      expect(@class_info).to eq "Module"
    end
  end
end
 

Но теперь, когда я запускаю rspec из командной строки, почему он возвращает следующую ошибку? (Примечание: несмотря на то, что в предыдущей настройке модульного тестирования RSpec # 1, которая была полностью аналогичной, я проверил, что могу успешно получить доступ к этому методу экземпляра Debug mixin)

 1) Debug#class_info? with mixins shows class info
   Failure/Error: @class_info = Debug.class_info?

   NoMethodError:
     undefined method `class_info?' for Debug:Module
 

Примечание: я поделился приведенным выше кодом в моем репозитории RubyTest на GitHub.

Настройка и рекомендации:

Моя система:

  • Ruby: ruby 2.3.0p0 ( ruby -v )
  • RSpec: 3.5.4 ( rspec -v )

Ссылки:

  • Применение примера из главы Mixins книги Programming Ruby

Ответ №1:

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

 require_relative '../../mixins/debug.rb'

class TestClass
  include Debug
end

RSpec.describe Debug, "#class_info?" do

  let(:test_instance) { TestClass.new }

  context "with mixins" do
    it "shows class info" do
      expect(test_instance.class_info?).to eq "TestClass"
    end
  end

end
 

Комментарии:

1. Я решаю свой первоначальный вопрос, перейдя class_info? на self.class_info? . Но в вашем примере test_instance.class_info? вызывается метод экземпляра модуля отладки суперкласса class_info? . Поэтому я обновил модуль отладки двумя методами: def class_info?; Debug.class_info?; end и def self.class_info?; "#{self.class.name}"; end . Чтобы ваш тест возвращал «TestClass» вместо «Module», я добавил переопределение для метода class_info? экземпляра в TestClass (т. Е. def class_info?; "#{self.class.name}" end ), чтобы он не вызывал метод экземпляра суперкласса