rspec testing has_many :through and after_save

前端 未结 3 1504
小鲜肉
小鲜肉 2021-02-06 11:20

I have an (I think) relatively straightforward has_many :through relationship with a join table:

class User < ActiveRecord::Base
  has_many :user         


        
3条回答
  •  终归单人心
    2021-02-06 12:00

    UPDATED ANSWER ** This passes rspec, without stubbing, running callbacks for save (after_save callback included ), and checks that @thing.followers is not empty before trying to access its elements. (;

    describe Thing do
      before :each do
        @user  = User.create(:name => "Fred");
        @thing = Thing.new(:name => 'Foo')
        @user.things << @thing
        @thing.run_callbacks(:save)
      end 
    
      it "should have created a relationship" do
        @thing.followers.should == [@user]
        puts @thing.followers.inspect
      end 
    end
    class Thing < ActiveRecord::Base
      after_save :some_function
      has_many :user_following_thing_relationships
      has_many :followers, :through => :user_following_thing_relationships, :source => :user
    
      def some_function
        the_followers = followers
        unless the_followers.empty?
          puts "accessing followers here: the_followers = #{the_followers.inspect}..."
        end
      end
    end
    

    ORIGINAL ANSWER **

    I was able to get things to work with the after_save callback, so long as I did not reference followers within the body / block of do_stuff. Do you have to reference followers in the real method you are calling from after_save ?

    Updated code to stub out callback. Now model can remain as you need it, we show @thing.followers is indeed set as we expected, and we can investigate the functionality of do_stuff / some_function via after_save in a different spec.

    I pushed a copy of the code here: https://github.com/kikuchiyo/RspecHasMany

    And spec passing thing* code is below:

    # thing_spec.rb
    require 'spec_helper'
    
    describe Thing do
        before :each do
            Thing.any_instance.stub(:some_function) { puts 'stubbed out...' }
            Thing.any_instance.should_receive(:some_function).once
            @thing = Thing.create(:name => "Foo");
            @user  = User.create(:name => "Fred");
            @user.things << @thing
        end
    
        it "should have created a relationship" do
            @thing.followers.should == [@user]
            puts @thing.followers.inspect
        end
    end
    # thing.rb
    class Thing < ActiveRecord::Base
        after_save :some_function
        has_many :user_following_thing_relationships
        has_many :followers, :through => :user_following_thing_relationships, :source => :user
    
        def some_function
            # well, lets me do this, but I cannot use @x without breaking the spec...
            @x = followers 
            puts 'testing puts hear shows up in standard output'
            x ||= 1
            puts "testing variable setting and getting here: #{x} == 1\n\t also shows up in standard output"
            begin
                # If no stubbing, this causes rspec to fail...
                puts "accessing followers here: @x = #{@x.inspect}..."
            rescue
                puts "and this is but this is never seen."
            end
        end
    end
    

提交回复
热议问题