Ruby:在代码块中更改类静态方法

给出Thread类的当前方法。 现在在测试中,我想这样做:

def test_alter_current_thread Thread.current = a_stubbed_method # do something that involve the work of Thread.current Thread.current = default_thread_current end 

基本上,我想在测试方法中更改类的方法,然后在之后恢复它。 我知道它对于另一种语言来说听起来很复杂,比如Java和C#(在Java中,只有强大的模拟框架才能做到)。 但它是ruby,我希望这些令人讨厌的东西可用

您可能想看看像Mocha这样的Ruby模拟框架,但是在使用纯Ruby方面,可以使用alias_method ( 此处的文档)来完成,例如

预先:

 class Thread class << self alias_method :old_current, :current end end 

然后定义你的新方法

 class Thread def self.current # implementation here end end 

然后恢复旧方法:

 class Thread class << self alias_method :current, :old_current end end 

更新以说明在测试中执行此操作

如果要在测试中执行此操作,可以按如下方式定义一些辅助方法:

 def replace_class_method(cls, meth, new_impl) cls.class_eval("class << self; alias_method :old_#{meth}, :#{meth}; end") cls.class_eval(new_impl) end def restore_class_method(cls, meth) cls.class_eval("class << self; alias_method :#{meth}, :old_#{meth}; end") end 

replace_class_method期望一个类常量,类方法的名称和新方法定义作为字符串。 restore_class_method获取类和方法名称,然后将原始方法替换为原位。

那么你的测试将遵循:

 def test new_impl = < 

您还可以编写一个小的包装器方法,它将替换方法,屈服于块,然后确保之后恢复原始方法,例如

 def with_replaced_method(cls, meth, new_impl) replace_class_method(cls, meth, new_impl) begin result = yield ensure restore_class_method(cls, meth) end return result end 

在您的测试方法中,这可以用作:

 with_replaced_method(Thread, 'current', new_impl) do # test code using the replaced method goes here end # after this point the original method definition is restored 

正如在原始答案中所提到的,您可能会找到一个框架来为您执行此操作,但希望上面的代码无论如何都是有趣和有用的。