开发者

Testing before_create method in rspec and rails 3

开发者 https://www.devze.com 2023-03-18 01:52 出处:网络
I\'ve looked into some tutes and all I saw were old posts on how to test before_create. Also it seems like they\'re all just testing that before_create was called i.e.:

I've looked into some tutes and all I saw were old posts on how to test before_create. Also it seems like they're all just testing that before_create was called i.e.:

@user = User.new
@user.should_receive(:method_name_called_by_before_create)
@user.send(:before_create) (sometimes they just do @user.save)

I want to actually test that my method worked and that it had assigned(and saved the variables) after creating the record.

Here are my models:

user.rb

class User < ActiveRecord::Base
  has_one :character, :dependent => :destroy

  after_create :generate_character

  private
    def generate_character
      self.create_character(:name => "#{email}'s avatar")
    end
end

and character.rb

class Character < ActiveRecord::Base

  belongs_to :user

  before_create :generate_character

  private
    def generate_character
      response = api_call
      #API CALL HERE

      #set object attributes here
      self.stat1 = calculate_stat1(response) + 5
      self.stat2 = calculate_stat2(response) + 5
      self.stat3 = calculate_stat3(response) + 5            
    end

    def api_call
      return api_call_response
    end

end

I want to test that generate character indeed 开发者_开发百科set the attributes without going online and calling the API call. Is this possible with rspec? I have a fixture of a json response so I was hoping I can stub out generate character and then use the fake response for testing.

Here's my character.spec:

describe Character do
  before(:each) do
    Character.any_instance.stub!(:api_call).and_return(fake_response.read)
    @user = Factory(:user)
    @character = @user.character
    puts  @character.inspect
end

def fake_response
  File.open("spec/fixtures/api_response.json")
end

It prints out only 5 for each of the character's stats. Also I did a puts response in the generate_character method in character.rb and it still prints out the "real" api call.

I managed to do a puts in fake_response and it does goes through there but it also goes through the "real" api_call after, which makes the stub obsolete. How do I get through this?


A good approach here is extracting your api call into a self contained method. Something like this:

class Character < ActiveRecord::Base
  belongs_to :user
  before_create :generate_character

  private
    def generate_character
      data = api_call

      #set object attributes from data
    end

    def api_call
      # returns a data structure
      # resulting from the call
    end
end

Then use RSpec's any_instance to stub the api_call method to return a fixed data structure

Character.any_instance.stub!(:api_call).and_return { {:id => 1, :attribute_one => "foo"} }
@user = User.create
@user.character.attribute_one.should == "foo"

for more info on any_instance check this commit

0

精彩评论

暂无评论...
验证码 换一张
取 消