RSPEC-设置ENV变量的最佳方法
我在模块上有类方法,然后放置一个常数,并将其称为
module Cryption
module Crypt
class << self
OFF_ENCRYPT = ENV['IS_OFF']
def encrypt
OFF_ENCRYPT
end
def decrypt
OFF_ENCRYPT
end
end
end
end
模块创建为gem
迫使我在要求之前设置环境变量
ENV["IS_OFF"] = "YES"
require "bundler/setup"
require "cryption"
Cryption::Crypt.encrypt
# result => "YES"
的每个类级别的方法“>
spec_helper.rb
require "bundler/setup"
require "cryption"
crypt_off_spec.rb
RSpec.describe "YES" do
before(:context) do
ENV['IS_OFF'] = "YES"
end
it "encryption off" do
expect(Cryption::Crypt.encrypt).to eq("YES")
end
end
crypt_on_spec.rb
RSpec.describe "NO" do
before(:context) do
ENV['IS_OFF'] = "NO"
end
it "encryption off" do
expect(Cryption::Crypt.encrypt).to eq("NO")
end
end
I have class methods on a module and put a CONSTANT and call it on each class-level method
module Cryption
module Crypt
class << self
OFF_ENCRYPT = ENV['IS_OFF']
def encrypt
OFF_ENCRYPT
end
def decrypt
OFF_ENCRYPT
end
end
end
end
That module created as a gem
That forces me to set environment variable before require the class
ENV["IS_OFF"] = "YES"
require "bundler/setup"
require "cryption"
Cryption::Crypt.encrypt
# result => "YES"
Is there the proper way set the environment variable on rspec, I think I can't set the variable after require the module
spec_helper.rb
require "bundler/setup"
require "cryption"
crypt_off_spec.rb
RSpec.describe "YES" do
before(:context) do
ENV['IS_OFF'] = "YES"
end
it "encryption off" do
expect(Cryption::Crypt.encrypt).to eq("YES")
end
end
crypt_on_spec.rb
RSpec.describe "NO" do
before(:context) do
ENV['IS_OFF'] = "NO"
end
it "encryption off" do
expect(Cryption::Crypt.encrypt).to eq("NO")
end
end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Env Vars并不应该在运行时更改。因此,在测试中调用
env ['is_off'] =“ no”
并不是一个好主意。问题是,env var是一种全局配置,因此,如果您从一个测试中更改它,则在运行另一个测试时仍将更改该值。最简单的方法可能是 stub_const 常数的值,例如
stub_const“ cryption :: crypt”,“ off_encrypt”,“ false”
。这是最好的选择,IMO。但是,为了完整,我可以向您展示一种实际更改特定测试的环境变量的方法。首先,您需要将常数更改为方法,例如
def off_encrypt; env [“ off_encrypt”];结束
。要么更改加密/解密
仅直接读取env var,例如不是从常数读取。然后,在您的测试中,您可以做这样的事情:
再次,我真的不建议这样做,但这是可能的。
Env vars aren't really supposed to be changed at runtime. So, calling
ENV['IS_OFF'] = "NO"
in your tests isn't really a good idea. The problem is, env vars are a global configuration, so if you change it from one test, the value will still be changed when you run the other test.The easiest way to do this is probably stub_const, which will temporarily change the value of the constant, e.g.
stub_const "Cryption::Crypt", "OFF_ENCRYPT", "false"
. This is the best option, imo.But for the sake of completeness, I can show you a way to actually change the environment variable from a specific test. First you would need to change the constant to a method, e.g.
def off_encrypt; ENV["OFF_ENCRYPT"]; end
. Either that or change theencrypt/decrypt
methods to just read the env var directly, e.g. not from a constant.Then, in your tests, you could do something like this:
Again, I wouldn't really recommend this, but it is possible.
来避免使用反模式
突变env:通常可以轻松避免使用一些最小的TDD重构ENV变量 。 ENV变量通过将ENV变量视为类或实例变量的目的。
从测试的角度来看,如果您想验证方法或类在ENV持有特定值时做正确的事情,则应设计您的应用程序以创建您关心的ENV值的副本,并根据需要突变。另外,如果您要测试是否正确拾取特定值,则可以分叉一个过程,然后更改叉子内的值,这不会影响该父过程。
我建议以下内容:
示例重构和一些测试骨架,
这将拾取您现有的环境价值,但是您现在拥有一个访问者,可以在其中根据需要更改特定测试。例如:
您还可以更新#New以获取关键字参数以覆盖默认值或执行其他操作。关键是Env应该提供不经常更改的默认值,您的类和方法应在必要时覆盖它们。这为测试提供了更大的灵活性。
您真正需要的唯一与ENV相关的测试是确保读取和解析正确的env值的测试,例如当它们不设置,无效或其他内容时。基于ENV变量的更改运行时行为只是一个反模式,因此这是重构的成熟。
Mutating ENV: Generally an Anti-Pattern Easily Avoided with Some Minimal TDD Refactoring
ENV variables are inherited from Ruby's process environment at startup, and while you can change an ENV variable for the current process and any subprocesses at runtime, you're essentially working against the purpose of ENV variables by treating ENV variables as class or instance variables.
From a testing perspective, if you want to validate that a method or class does the right thing when ENV holds a particular value, you should design your application to create a copy of the ENV values you care about, and mutate those as needed. Alternatively, if you're testing whether specific values are properly picked up, you can fork a process and then change the value within the fork, which will not affect that parent process.
Here's what I'd recommend:
Example Refactoring and Some Test Skeletons
This will pick up your existing environment value, but you now have an accessor where you can change it as needed for specific tests. For example:
You could also update #new to take a keyword argument to override the default value, or perform other actions. The point is that ENV should provide defaults that don't change often, and your classes and methods should override them when necessary. This provides more flexibility for tests.
The only ENV-related tests you should really need are those that ensure that the ENV values are read and parsed correct, such as when they are unset, invalid, or whatever. Changing runtime behavior based on ENV variables is just an anti-pattern, so this is ripe for refactoring.