I have a model, which is using attr_encrypted gem to encrypt the password.
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 I am learning to write test cases and my factory for the above looks like this:
FactoryBot.define do factory :credential do user_name { "rmishra" } user_pass { "secret" } credential_type { "linux" } encryption_key { "abcdefghijklmnopqrstuvw123456789" } end end My spec file looks like:
RSpec.describe Credential, type: :model do let(:credential) { create(:credential) } ... end How do I stub encryption_key method in factory definition, which is getting used at the time of create?
1 Answer
Since encryption_key is not an attribute on your model, you can't configure it in your factory.
encryption_key is called automatically by the attr_encrypted gem when you assign user_pass to a Credential object. In this case that's done by the factory.
I would move the logic in your encryption_key method into a class to facilitate testing:
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 Then, in my test, I would stub the 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 Encapsulating your encryption key generation logic into a separate object decouples it from your model, allowing you to easily test that logic without having to create a Credential object.