我在模塊上有類方法并放置一個 CONSTANT 并在每個類級方法上呼叫它
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"
有沒有正確的方法在rspec上設定環境變數,我想我在需要模塊后無法設定變數
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
uj5u.com熱心網友回復:
環境變數實際上不應該在運行時更改。所以,呼叫 ENV['IS_OFF'] = "NO"你的測驗并不是一個好主意。問題是,env vars 是一個全域配置,所以如果你從一個測驗改變它,當你運行另一個測驗時,值仍然會改變。
最簡單的方法可能是stub_const,它會暫時改變常量的值,例如stub_const "Cryption::Crypt", "OFF_ENCRYPT", "false". 這是最好的選擇,imo。
但為了完整起見,我可以向您展示一種從特定測驗中實際更改環境變數的方法。首先,您需要將常量更改為方法,例如def off_encrypt; ENV["OFF_ENCRYPT"]; end. 要么改變encrypt/decrypt方法,要么直接讀取 env var,例如不從常量讀取。
然后,在您的測驗中,您可以執行以下操作:
around(:each) do |example|
orig_value = ENV["OFF_ENCRYPT"]
ENV["OFF_ENCRYPT"] = "true" # set the new value
example.run
ensure
ENV["OFF_ENCRYPT"] = orig_value
end
同樣,我不會真的推薦這個,但這是可能的。
uj5u.com熱心網友回復:
變異 ENV:通常是通過一些最小的 TDD 重構輕松避免的反模式
ENV 變數在啟動時繼承自 Ruby 的行程環境,雖然您可以在運行時更改當前行程和任何子行程的 ENV 變數,但實際上通過將 ENV 變數視為類或實體變數,這違背了 ENV 變數的目的。
從測驗的角度來看,如果您想驗證一個方法或類在 ENV 擁有特定值時是否正確,您應該設計您的應用程式以創建您關心的 ENV 值的副本,并根據需要更改這些值。或者,如果您正在測驗是否正確提取了特定值,您可以派生一個行程,然后在派生中更改該值,這不會影響該父行程。
這是我的建議:
- 重構您的類以使用 ENV 變數作為默認值。
- 重構您的類以啟用測驗或運行時行為以覆寫默認值。
- 構建測驗以確保 ENV["ENCRYPTION_ENABLED"](或任何您想命名的名稱)有效,并且可以在測驗中或運行時輕松修改。
示例重構和一些測驗框架
class Foo
attr_accessor :encryption_enabled
# set a default of true (or false if you prefer), or take an
# optional keyword argument like encryption_enabled: true
# when you initialize an instance of your class
def initialize
@encryption_enabled = ENV.fetch "ENCRYPTION_ENABLED", true
end
end
這將獲取您現有的環境值,但您現在有一個訪問器,您可以在其中根據特定測驗的需要更改它。例如:
Rspec.describe Foo
describe "#encryption_enabled" do
it "sets an instance variable based on ENV['ENCRYPTION_ENABLED']" do
pending
end
it "defaults to 'true' if ENV['ENCRYPTION_ENABLED'] is unset" do
pending
end
it "can be set to 'false' via its accessor" do
subject.encryption_enabled = false
expect(subject).to be_false
end
end
end
您還可以更新 #new 以采用關鍵字引數來覆寫默認值,或執行其他操作。關鍵是 ENV 應該提供不經常更改的默認值,并且您的類和方法應該在必要時覆寫它們。這為測驗提供了更大的靈活性。
您真正需要的唯一與 ENV 相關的測驗是那些確保 ENV 值被正確讀取和決議的測驗,例如當它們未設定、無效或其他情況時。基于 ENV 變數更改運行時行為只是一種反模式,因此重構的時機已經成熟。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/498161.html
