64

是的,我知道,测试私有方法不是一个好主意(我读了这个线程 - 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

将私有方法重构为新对象本质上就像我将它们设为公共(并且使用一种方法进行类 - 这是毫无意义的

编辑: 这更多是关于干净代码和正确测试的理论问题。在我的第一个链接中,人们认为测试私有方法很差。我不想作弊#send,但我也没有看到任何可行的重构方法

4

3 回答 3

122

您可以使用方法在sendruby​​ 中调用私有方法。像这样的东西:

@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
于 2013-05-16T23:49:57.797 回答
16

撇开是否应该测试私有方法的问题不谈,在 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
于 2013-05-17T01:48:09.267 回答
3

您可能在您提到的所有资源中都听到了这种想法,但正确的“理论”方法是测试@client接收add_message_callback,然后使用集成测试间接测试您的私有方法。单元测试的重点是你可以改变实现,你的测试仍然会通过

于 2013-05-17T00:10:09.200 回答