简体   繁体   中英

Rspec Test validations of 'on: : update' not working (Rails4/Rspec 3)

I have a model where I implemented a validate to prevent change after the initial value has been set (during the object creation).

It works this way:

models/deal.rb

validate :quantity_not_changeable, on: :update

def quantity_not_changeable
      if quantity_changed?
        errors.add(:quantity,
         "Change of the initially defined qty is not possible")
      end
    end

This works in my app: I created a new Deal, it works. I try to edit it by changing the 'quantity' field, it fails. I try to edit another field (apart from 'quantity'), it works. so all is working.

But my Rspec Test to test it FAILS.

Actually I know it does NOT work because there is a problem with on: : validate.

Indeed WITHOUT the 'on: : validate', the test passes, but of course I can't just remove 'on: :update', as I only want the user not to be able to edit it after the initial creation of the Deal).

describe Deal do

  let(:admin_user) { FactoryGirl.create(:admin_user) }

  before(:each) do
    @attr = {
      title:                              "Neque porro quisquam est qui dolorem",
      description:                        "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum",
      quantity:  10
    }
  end

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      deal.update(quantity: 15)     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

but I get this rspec error:

Failure/Error: expect(deal).to have(1).errors_on(:quantity)
       expected 1 errors on :quantity, got 0

I am going to use below "print variable": p Deal to show you WHY I am sure it is due to on: :update which is not working in TESTS.

FIRST: if I place 'p deal' just before updating it, let's see the value of the deal object:

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      p deal
      deal.update(quantity: 15)     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

I get the following output (we see that all is normal: quantity is indeed 10)

#<title: "Neque porro quisquam est qui dolorem", description: "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lo...", quantity: 10>

SECOND: now let's move the 'p deal' AFTER my attempt in the test to update the value of 'quantity'

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      deal.update(quantity: 15)
      p deal     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

Now the output is:( we see that CONTRARY to what we could expect due to the validate on: :update in the code, the Rspec test does manage unfortunately to update the value of quantity ):

#<title: "Neque porro quisquam est qui dolorem", description: "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lo...", quantity: 15>

So I don't understand why in reality, I tested manually and can not update, but in my rspec test suite it does update!!!

Hours to understand it but to no success...I tried to find some online resources and some say on: :update is a weak way to do things . I really don't know what to do with this weird bug.

Please help.

I guess entry isn't saved when called create method because of other validation. You can try open up a console with rails c and evaluate following:

deal = Deal.create(title: 'mytitle', description: 'mydescription', quantity: 10)
deal.persisted?

then if you got false in order to find out what errors were when creating:

deal.errors.messages

EDIT

This test should passes:

it "fails if initial quantity is changed" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages).to eq({quantity: ["Change of the initially defined qty is not possible"]})
end

But these should not:

it "exploited test that should not pass because messages hash should not be empty" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages.empty?).to eq(true)
end

it "exploited test in other variation" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages).to eq({})
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