我有一个模型,它使用attr_encrypted
gem来加密密码。
class Credential < ApplicationRecord
validates :user_name, presence: true
enum credential_type: { windows: 1, linux: 2 }
attr_encrypted :user_pass, key: :encryption_key
def encryption_key
# Some complex logic
end
end
我正在学习编写测试用例,我的工厂看起来像这样:
FactoryBot.define do
factory :credential do
user_name { "rmishra" }
user_pass { "secret" }
credential_type { "linux" }
encryption_key { "abcdefghijklmnopqrstuvw123456789" }
end
end
我的规范文件如下所示:
RSpec.describe Credential, type: :model do
let(:credential) { create(:credential) }
...
end
如何在工厂定义中存根encryption_key
方法,该方法在create
时使用?
由于encryption_key
不是模型上的属性,因此无法在工厂中对其进行配置。
当您将user_pass
分配给Credential
对象时,attr_encrypted
gem 会自动调用encryption_key
。在这种情况下,这是由工厂完成的。
我会将encryption_key
方法中的逻辑移动到一个类中以方便测试:
class Credential < ApplicationRecord
validates :user_name, presence: true
enum credential_type: { windows: 1, linux: 2 }
attr_encrypted :user_pass, key: :encryption_key
def encryption_key
EncryptionKeyGenerator.generate # or whatever name makes more sense
end
end
然后,在我的测试中,我会存根EncryptionKeyGenerator
:
RSpec.describe Credential, type: :model do
let(:credential) { create(:credential) }
let(:encryption_key) { "abcdefghijklmnopqrstuvw123456789" }
before do
allow(EncryptionKeyGenerator).to receive(:generate).and_return(encryption_key)
end
...
end
将加密密钥生成逻辑封装到单独的对象中可将其与模型分离,从而可以轻松测试该逻辑,而无需创建Credential
对象。