Подтвердить что ты не робот

Тестирование частного метода в Ruby (rspec)

Да, я знаю, что тестирование частных методов это не очень хорошая идея (и я прочитайте эту тему - http://www.ruby-forum.com/topic/197346 - и некоторые другие)

Но как я могу проверить следующий код?

Я использую xmpp4r. В моем общедоступном методе #listen я начинаю получать jabber такие сообщения:

def listen
  @client.add_message_callback do |m|
    do_things_with_message(m)
  end
end

private
def do_things_with_message(m)
  #
end

#add_message_callback - запускает блок, когда приходит сообщение (в другом потоке)

Итак, тестирование метода #listen затруднено, и он больше тестирует xmpp4r чем мой #do_things_with_message

Как сделать все правильно и проверить #do_things_with_message?:) (http://www.ruby-forum.com/topic/197346#859664)

Частные методы рефакторинга для нового важного объекта будут такими, как я делаю их публичными (и класс с одним методом - это бессмысленно

EDIT: Это скорее теоретический вопрос о чистом коде и правильных тестах. В моей первой ссылке люди утверждают, что тесты частных методов плохо. Я не хочу обманывать с #send, но также я не вижу никаких жизнеспособных способов рефакторинга

4b9b3361

Ответ 1

Вы можете вызвать частный метод в ruby, используя метод send. Что-то вроде этого:

@my_object = MyObject.new
@my_object.send(:do_things_with_message, some_message)

В тесте, который будет выглядеть примерно так:

it "should do a thing" do
  my_object = MyObject.new
  my_object.send(:do_things_with_message, some_message)
  my_object.thing.should == true
end

Ответ 2

Отложив вопрос о том, следует ли тестировать частный метод, в Ruby очень возможно временно открыть закрытый метод. Вот что я имею в виду:

# Metaprogrammatical magic to temporarily expose
# a Class' privates (methods).
class Class
  def publicize_methods
    saved_private_instance_methods = self.private_instance_methods
    self.class_eval { public *saved_private_instance_methods }
    yield
    self.class_eval { private *saved_private_instance_methods }
  end
end

Вы использовали бы publicize_methods следующим образом:

ClassToTest.publicize_methods do
  ...
  do_private_things_with_message(m).should ???
  ...
end

Ответ 3

Вероятно, вы слышали эту мысль во всех ресурсах, которые вы упомянули, но правильный "теоретический" способ сделать это - проверить, что @client получает add_message_callback, а затем косвенно тестирует ваши частные методы с помощью тестов интеграции. Вся цель модульного тестирования заключается в том, что вы можете изменить реализацию, и ваши тесты все равно пройдут