Sinscary Sinscary - 4 months ago 29
Ruby Question

stub random value in rspec with secure_random

I am trying to write specs for my gem, which generates otp and saves it in db. Now i am writing specs for it. so basically i have three methods

generate_otp!
,
regenerate_otp!
,
verify_otp(otp)
. what
generate_otp!
does is it calls a method
generate_otp
which contains three variables


  1. otp_code
    - basically a random value generated using secure_random

  2. otp_verified
    - a boolean value to set the status whether otp is verified or not

  3. otp_expiry_time
    - sets expiry time for otp which can be set by rails app in configuration.



these all three are columns of my db also.

Now after
generate_otp
i am calling
active_records
's
save
method to save values to db.

Now for testing i am using in
:memory:
and storing values in table. after testing i am dropping the db. Now i am not getting how to stub the randomly generated value and test whether value is assigned or not to all three columns, i.e,
otp_code
,
otp_verified
,
otp_expiry_time
.

Here is code for my methods which i need to test.

def generate_otp
self.otp_verified = false
self.otp_expiry_time = OtpGenerator::configuration.otp_expiry_time
self.otp_code = SecureRandom.hex(4)
end

def generate_otp!
generate_otp
save
end


Any help with this ? I have also checked this question, but not much helpful. It's first time i am writing specs and really don't have that much experience with rspecs. I have also studied the official documentation for mock and stub, but i am really getting confused.

update : otp_spec code

require 'spec_helper'

describe OtpGenerator do

let(:user) { build_mock_class.new() }
before(:all) { create_table }
after(:all) { drop_table }

describe '#generate_otp' do
it 'generate otp and save it' do
user.generate_otp!

end
end

describe '#regenerate_otp' do
it 'regenerate otp and save it' do

end
end

describe '#verify_otp' do
it 'verifies otp' do

end
end

def build_mock_class
Class.new(ActiveRecord::Base) do
self.table_name = 'mock_table'
include OtpGenerator
end
end

def create_table
ActiveRecord::Base.connection.create_table :mock_table do |t|
t.string :otp_code
t.boolean :otp_verified
t.datetime :otp_expiry_time
end
end

def drop_table
ActiveRecord::Base.connection.drop_table :mock_table
end
end

Answer

A direct approach to stubbing out the SecureRandom method in rspec would be as follows:

before { allow(SecureRandom).to receive(:hex).with(4).and_return('abcd1234') }

You can then check that 'abcd1234' is stored in the database. In order to keep the test DRY, you may also wish to reference this as a variable, e.g. let(:random_value) { 'abcd1234' }.

Comments