Как установить частную переменную экземпляра, используемую в тесте метода? - PullRequest
45 голосов
/ 27 января 2012

Имеется класс с парой переменных экземпляра и некоторыми методами.Некоторые переменные экземпляра доступны через attr_reader и attr_accessor.Таким образом, другие являются частными.
Некоторые из частных переменных экземпляра устанавливаются в одном из методов экземпляра и считываются / используются в другом методе.

Для тестирования я использую RSpec.Поскольку я все еще новичок в Ruby и хочу все сделать правильно, я определил, что мои тесты достаточно тонкие.Таким образом, у меня есть один describe блок для каждого метода экземпляра, который сам разделен на подмножество context s и it s.Общие условия среды определяются с помощью before.

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

Есть ли способ принудительно установить частную переменную экземпляра для определенного значения.Аналогично « вырыванию » значения закрытой переменной экземпляра с Object::instance_eval(:var).

Ответы [ 3 ]

84 голосов
/ 27 января 2012

Как вы ответили в своем вопросе, самый простой способ установить переменную экземпляра - это метод instance_eval:

obj.instance_eval('@a = 1')

Другой способ - использовать instance_variable_set:

obj.instance_variable_set(:@a, 1)

Но яне рекомендую делать это в ваших спецификациях.Все спецификации посвящены тестированию поведения объекта и тестированию поведения путем нарушения инкапсуляции класса с помощью instance_eval, что сделает ваши тесты более хрупкими и зависящими от реализации.

Альтернативный подход к изоляции состояния объекта заключается в заглушке методов доступа:

class UnderTest
  attr_accessor :a

  def test_this
    do_something if a == 1
  end
end

#in your test
under_test = UnderTest.new
under_test.stub(:a).and_return(1)
8 голосов
/ 27 января 2012

Использование instance_variable_set:

class SomeClass
  attr_reader :hello
  def initialize
    @hello = 5
  end
  # ...
end

a = SomeClass.new
a.hello    # => 5

a.instance_variable_set("@hello", 7)
a.hello    # => 7
0 голосов
/ 04 апреля 2019

Я только что решил, создав дочерний элемент и добавив метод доступа:

class HasSecrets
  @muahaha
end

class TestMe < HasSecrets
  attr_accessor(:muahaha)
end

def test_stuff
  pwned = TestMe.new()
  pwned.muahaha = 'calc.exe'
end
...