Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby on Rails: should all my ActiveRecord callback methods be private?

I have an ActiveRecord model which has some callbacks and custom validations I want to test. It means, that I have to make all of them public. Is that a good practice or is there a better solution in this case?

Examples of the methods I want to test:

  def before_validation
    original.edit(self) if original
  end

  validate :unique?, on: :create

  def unique?
    return true if original.blank?
    errors.add(:base, 'The entry already exists')
    false
   end

In other words:

  1. If I want to test "before_validation" method, do I have to make it public and call test_object.before_validation directly in my model Rspec file?
  2. If I want to test not only, that custom validation method unique?() is called on validation, but also, the method itself, do I have to make the unique?() public as well?

The problem is, that neither of these methods I am using outside my of model (so they they should be private), but how could I test without making them public?

like image 720
krn Avatar asked Jun 11 '12 14:06

krn


1 Answers

It's easy to get caught up in testing implementation, but this is a good candidate for testing behaviour.

Ask yourself, what is your before validation really doing? Then make yourself a test that, given certain inputs, you'll get certain outputs if and only if your before validation works.

As a simple example, imagine you have a user model with a simple name attribute, and you have a before_validation that simply does:

name = "Auto-generated name." if name.blank?

Then you could write a test for it like this:

it "gets an auto-generated name if none is specified." do
    user = User.create!
    user.name.should eq "Auto-generated name."
end

it "does not get an auto-generated name if one is specified." do
    user = User.create!(:name => "Test Name")
    user.name.should eq "Test Name"
end

So as you can see, this test does test the validation, but it doesn't need it to be public, because you're just testing the behaviour of it. The same goes for your unique? method. Give it certain inputs and test the behaviour, without having to care about which specific method was used or any other implementation details.

like image 180
MrDanA Avatar answered Nov 15 '22 03:11

MrDanA