How to check after_initialize rail model callback?

I use FactoryGirl and Rspec for testing. The model sets the foreign key after init, if it is zero. Therefore, it uses data from another association. But how can I check this? I usually used factory to create this object and used stub_chain for "self.user.main_address.country_id". But with the creation of this object, after initialization will be called. I have no chance of drowning him.

after_initialize do if self.country_id.nil? self.country_id = self.user.main_address.country_id || Country.first.id end end 

Any idea?

+7
source share
3 answers

Ideally, it is better to test the behavior instead of the implementation. Verify that the foreign key is being installed instead of verifying that the method is called.

Although, if you want to test the after_initialize here, it works.

 obj = Model.allocate obj.should_receive(:method_here) obj.send(:initialize) 

Allocate places an object in memory but does not call initialize . After setting the wait, you can call initialization and catch the method call.

+9
source

The Orlando method works, and here is another one I would like to add. (Using the new rspec "expect" syntax)

 expect_any_instance_of(Model).to receive(:method_here) Model.new 
+6
source

Another approach is to refactor your code to allow simple unit tests. This way, your code approaches the upper limit of how much code I would put in the callback:

 after_initialize do if self.country_id.nil? self.country_id = self.user.main_address.country_id || Country.first.id end end 

If it grew much more, I would extract it into a method and reduce your callback to a method call:

 after_initialize :init_country_id def init_country_id if self.country_id.nil? self.country_id = self.user.main_address.country_id || Country.first.id end end 

The bonus here is that testing init_country_id becomes yet another unit test method at the moment ... there is nothing special about this.

Now that you have a unit behavior test, you can also verify that it is being called if you have doubts. (Something after_initialize :init_country_id as simple as after_initialize :init_country_id does not require testing calls, IMO)

You can use gem shoulda-callback-matchers to verify that your callbacks actually run, as intended:

  it { is_expected.to callback(:init_country_id).before(:initialize) } 
0
source

Source: https://habr.com/ru/post/897210/


All Articles