在“ main”对象上调用RSpec测试方法

时间:2018-08-08 07:27:05

标签: ruby rspec

有时,我们在ruby main对象上调用方法。例如,我们为FactoryBot调用create,为I18n调用_()

测试这些在RSpec中调用的顶级方法的正确方法是什么?

例如,我要测试N_是否被调用,但是由于Rspec中的self和文件中的self不同,因此无法正常工作。

# spec
describe 'unfound_translations' do
  it 'includes dynamic translations' do
    expect(self).to receive(:N_)
    load '/path/to/unfound_translations.rb')
  end
end

# unfound_translations.rb
N_('foo')

但是这没有通过。

1 个答案:

答案 0 :(得分:1)

好的,我现在解决你的问题。您的主要问题是self块中的itself内部的unfound_translations.rb不同。因此,您要在一个对象上设置期望值,而在完全不同的对象上调用方法N_

(编辑:我刚刚意识到,当再次阅读该问题的主题时,您已经意识到了。很抱歉声明明显的问题……将其保留下来,对其他人可能有用)

我设法拥有一种有效的hacky方式,这里是:

# missing_translations.rb
N_('foo')

和规范(为简单起见,我在其中定义了一个用于测试的简单模块):

module N
  def N_(what)
    puts what
  end
end

RSpec.describe 'foo' do
  let(:klass) do
    Class.new do
      extend N
    end
  end

  it do
    expect(klass).to receive(:N_)
    klass.class_eval do
      eval(File.read('missing_translations.rb'))
    end
  end
end

它的作用是创建一个匿名类。评估内部missing_translations.rb的内容意味着klass是接收thing方法的N_。因此,您可以在那里设定期望。

我很确定您可以将extend N模块替换为任何给您提供N_方法的模块,这应该可以工作。

这很hacky,但工作量不大,因此在提供更优雅的解决方案之前可能就足够了。