Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 222
Sinscary Avatar asked Jul 14 '16 09:07

Sinscary


Video Answer


1 Answers

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' }.

like image 128
Tom Lord Avatar answered Sep 19 '22 19:09

Tom Lord