Testing against mass assignment
Asked Answered
T

3

5

Maybe this isn't something that needs to be tested against, but I'm learning so I don't think its wrong to test to the max.

I have several tests that all produce the expected results except for one. I found a way of working around it but I wondered what the correct method would be.

When I test saving in rails console it doesn't save the admin field from the params hash, which is what I expect. When I build with a factory then save it, validations pass/fail accordingly. When I test for protection against mass assignment the test fails (because it sets the admin field when I expect it not to)

Any thoughts, suggestions or concerns?

Thanks

Model:

class User ...
  #id, name, email, admin(int)
  attr_accesible :name, email
  ...
end

user_spec

it "should not have an admin after a mass save" do
  user = Factory.build(:user)
  user.save
  user.admin.should be_nil    #its not nil, its 0     
end

factories

Factory.define :user do |f|
  f.name "rec_acro"
  f.email "[email protected]"
  f.admin 0
end
Triarchy answered 5/5, 2011 at 3:1 Comment(0)
P
12

You can use Shoulda on top of rspec to get a concise mass assignment spec:

describe User do
  it { should_not allow_mass_assignment_of(:admin) }
end
Pottery answered 5/5, 2011 at 3:22 Comment(6)
You don't need to use RSpec to use Shoulda.Tracery
Right, but since the OP is already using rspec, I was just pointing out that they could be used together.Pottery
Do you think then that only person who will ever read this question and answer looking for help is the OP? I was noting it for others.Tracery
I'm sorry if you misinterpreted my response, but that's not what I was thinking.Pottery
@JordonBedwell Can you explain what you mean by that? Rails doesn't treat mass assignment any differently between new and create.Pottery
This answer is a year and a half old. If you you have a better way to do it, then please create a new answer so others will actually see it. Pointing out a flaw in what I suggested without providing an alternative isn't benefitting people who may stumble on this in the future.Pottery
P
3

FactoryGirl will take each attribute in the Factory definition and set it individually. So your test actually doesn't test mass assignment

From the FactoryGirl code (build.rb):

  def set(attribute, value)
    @instance.send(:"#{attribute}=", value)
  end

(See this if you're interested in more code reading for the FactoryGirl gem.)

As another answer suggested, you can use the Shoulda to employ the allow_mass_assignment_of matcher. It basically does something like:

it "allows mass assignment of :title" do
  accessible = Post.accessible_attributes.include?('title') ||
             !Post.protected_attributes.include?('title')
  accessible.should be_true
end

(Here's a little more about about Should matchers.)

Propagate answered 5/5, 2011 at 3:34 Comment(0)
T
2

Factory Girl (rightfully so) doesn't use mass assignment to generate objects. Take the generated user object from the factory and then attempt to do mass assignment on it, albeit with just the admin parameter.

Tracery answered 5/5, 2011 at 3:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.