Rspec-是否可以对哈希进行存根

时间:2019-03-06 04:00:04

标签: ruby rspec

我正在做一些单元测试。其中一个使用在我的应用程序MyBigApp::Env中设置的特定配置变量,如下所示:

{:country=>'uk', :another_hosts=>["192.168.99.105"]}

所以我用MyBigApp::Env.country

访问它

但是在我的单元测试中,我希望测试的country变得有用。

使用rspec我已经看到了存根,但是无法使其正常工作-我出错的任何想法:

MyBigApp::Env.stub(:[]).with('country').and_return('gr')

也尝试过此操作(如上所示,已弃用):

allow(MyBigApp::Env).to receive('country').and_return('gr')

事实上,我也尝试过:

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
p my_hash

并且没有更新-它只是返回{:uri=>nil}

作为一种解决方法,此刻,我必须将环境变量保存在before(each)块中的临时变量中,然后将其返回到after(each)中的原始变量。这对我来说真的很冒险。我在想,如果服务正在运行,并且有人在运行单元测试,那么在测试正在运行的那个小实例中,它可能会影响最终用户。

任何帮助将不胜感激。

谢谢

3 个答案:

答案 0 :(得分:1)

是的,但是请记住,存根仅在触发/调用存根/模拟的方法时起作用

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
p my_hash[:url] # it will be 'Over written!'

答案 1 :(得分:0)

这对我有用:

my_hash = {:uri=>nil}
allow(my_hash).to receive(:[]).with(:uri).and_return('Over written!')
expect(my_hash[:uri]).to eq "Over written!"

在示例测试用例中,您只是在调用p my_hash,而实际上并没有调用[]方法。

关于为什么MyBigApp::Env不起作用,这实际上取决于它是什么类。可能无论使用哪种方法.country都不会实际调用[]

真的,如果您致电MyBigApp::Env['country']并存根MyBigApp::Env[]接收'country',则应该起作用。

关于您是否希望通过测试来更改正在运行的应用程序的行为……这些是什么样的测试?针对实时生产应用程序运行单元测试非常奇怪。您如何看待它将改变您的生产应用程序的代码? Env哈希仅存在于内存中吗?

无论如何,您永远不必担心测试会改变“最终用户”的体验。始终在完全隔离的环境中运行测试,这意味着不要使用相同的数据库。实际上,通常在每次测试后都会擦除测试数据库。

答案 2 :(得分:0)

只是想提出一个非存根的替代方案。例如:

def code_under_test
  key = 'country'

  # ... maybe lots of code

  value = MyBigApp::Env[key] # deep inside some classes

  # ... lots more code

  "This is the #{value}"
end

MyBigApp::Env在代码的深处进行了硬编码,对存根的需求表明该依赖关系以及OOP封装的好处都丧失了。

如果是这种情况,那就容易多了:

def code_under_test(config_vars = MyBigApp::Env)
  "This is the #{config_vars['country']}"
end

it 'should return my country value' do
  value = previous_code_under_test('country' => 'TEST VALUE')
  expect(value).to eq("This is the TEST VALUE")
end

不需要存根,只需普通的旧方法调用即可。