Тестирование частного метода в 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
, но также я не вижу никаких жизнеспособных способов рефакторинга
Ответы
Ответ 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
, а затем косвенно тестирует ваши частные методы с помощью тестов интеграции. Вся цель модульного тестирования заключается в том, что вы можете изменить реализацию, и ваши тесты все равно пройдут