2011-07-07 69 views
1

我已经研究过一些tutes,我看到的都是关于如何测试before_create旧文章。此外,它好像他们都只是测试这before_create被称为即:测试在rspec的before_create方法和轨道3

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

我想实际测试我的方法工作,它已分配(和保存的变量)创建记录后。

这里是我的模型:

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 

和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 

我想测试生成字符确实设置的属性无需上网,并呼吁API调用。这可能与rspec?我有一个json响应的固定装置,所以我希望能够将生成的字符存根删除,然后使用假响应进行测试。

这里是我的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 

它打印出来只有5对每个人物的统计资料。我还在character.rb的generate_character方法中做了puts response,它仍然打印出“真正的”api调用。

我能够做到在fake_response一放,它并经过那里,但它也经历了“真正的” api_call之后,这使得短线过时。我如何解决这个问题?

回答

4

这里一个好的方法是提取您的API调用到一个自包含的方法。事情是这样的:

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 

然后需要Rspec的any_instance存根的api_call方法返回一个固定的数据结构

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

更多的信息上any_instance支票上但this commit

+0

嗯还是让我检查看起来非常有前途的人只是一个问题,我已经有一个固定装置,我保存为“样品response.json”,难道我只是做一个File.open(“样品fixture.json”)在我的and_return电话? – corroded

+0

是的!如果您在#generate_character方法中处理解析该JSON,则可以从and_return调用返回JSON fixture。 – pigoz

+0

嗯想起来了,我居然把在generate_character方法的API调用,这样我就只有一次调用它,而不是三次。比方说,我使用该API响应设置3个属性。所以如果我把它放在一个单独的方法,那将需要3次调用,而不是我把它的响应放在一个变量中,并在generate_character中调用一次...对吧? – corroded