简体   繁体   中英

How to test a specific line in a rails model using rspec

I have a model with an initializer in it, which basically creates a user from a user hash.

After it gets the user information, it checks whether the "privileges" key in the hash is an array. If it's not, it turns it into an array.

Now the obvious way of doing this would be crafting an entire user_hash so that it would skip those "create user" lines and then check if it turns the input into an array if necessary. However, I was wondering if there is a more DRY way of doing this?

Here is the user model I'm talking about:

def initialize(opts={})
  @first_name = opts[:user_hash][:first]
  @last_name = opts[:user_hash][:last]
  @user_name = opts[:user_hash][:user_name]
  @email = opts[:user_hash][:email]
  @user_id = opts[:user_hash][:id]

  @privileges = {}

  if opts[:privs].present?
    if !opts[:privs].kind_of?(Array)
      opts[:privs] = [opts[:privs]]
    end
  end
end

You can pass a double which returns the needed value when the proper key is requested, and itself (or something else) otherwise:

it 'turns privs into an array' do
  opts = double(:opts)
  allow(opts)to receive(:[]).and_return(opts)
  allow(opts)to receive(:[]).with(:privs).and_return('not array')

  expect(MyClass.new(opts).privileges).to eq(['not array'])
end

Btw, your code could be simplified using the splat operator:

privs = [*opts[:privs]]

sample behavior:

privs = nil
[*privs]
# => []

privs = ['my', 'array']
[*privs]
# => ["my", "array"]

privs = 'my array'
[*privs]
# => ["my array"]

You can even use the idempotent Kernel#Array

def initialize(opts = {})
  @first_name = opts[:user_hash][:first]
  @last_name = opts[:user_hash][:last]
  @user_name = opts[:user_hash][:user_name]
  @email = opts[:user_hash][:email]
  @user_id = opts[:user_hash][:id]
  @privileges = {}

  Array(opts[:privs])
end

I hope that helps

Rather than testing the implementation (value is turned into an array), I would test the desired behavior (takes single privilege or multiple privileges):

describe User do

  describe '#initialize' do

    it "takes single privilege" do
      user = User.new(user_hash: {}, privs: 'foo')
      expect(user.privileges).to eq(['foo'])
    end

    it "takes multiple privileges" do
      user = User.new(user_hash: {}, privs: ['foo', 'bar'])
      expect(user.privileges).to eq(['foo', 'bar'])
    end

  end

end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM