2010-10-20 63 views
4

这里的模型规范是,我使用的模型,我已经简化了一点下来还是失败,我列举了最简单的形式:测试使用的after_create回调

class User < ActiveRecord::Base 
    after_create :setup_lists 

    def setup_lists 
    List.create(:user_id => self.id, :name => "current") 
    List.create(:user_id => self.id, :name => "master") 
    end 
end 

而且我倒要符合规范的举例如下:

require 'spec_helper' 

describe User do 
    before(:each) do 
    @user = Factory(:user) 
    end 

    describe "#setup_lists" do 
    before(:each) do 
    List.stub(:create).with(:name => "current") 
    List.stub(:create).with(:name => "master") 

    it "creates a new master list" do 
     List.should_receive(:create).with(:name => "master") 
    end 

    it "creates a new current list" do 
     List.should_receive(:create).with(:name => "current") 
    end 
    end 
end 

其中我预计会工作得很好,但我留下了以下错误:

Failures: 
    1) User#setup_lists creates a new master list 
    Failure/Error: List.should_receive(:create).with(:name => "current") 
    (<List(id: integer, name: string, created_at: datetime, updated_at: datetime, user_id: integer) (class)>).create({:name=>"current"}) 
     expected: 1 time 
     received: 0 times 
    # ./spec/models/user_spec.rb:44 

    2) User#setup_lists creates a new current list 
    Failure/Error: List.should_receive(:create).with(:name => "master") 
    (<List(id: integer, name: string, created_at: datetime, updated_at: datetime,  user_id: integer) (class)>).create({:name=>"master"}) 
    expected: 1 time 
    received: 0 times 
    # ./spec/models/user_spec.rb:48 

任何人都可以帮助我理解为什么会发生这种情况吗?

回答

4

三个问题:

1)用户对象被设置消息的期望,所以should_receive永远不会看到该消息之前创建的;

2)您正在为您设定预期的方法残缺。你想存根出方法,你组的期望,但其所需的测试通过

3)你必须在所有的参数

要修正通过,创建用户设置expectaion后反对,并踩灭反过来每个方法(因为你的模式要求List.create两次):

describe User do 
    describe "#setup_lists" do 
    it "creates a new master list" do 
     List.stub(:create).with(:user_id=>1,:name => "current") 
     List.should_receive(:create).with(:user_id=>1,:name => "master") 
     @user = User.create 
    end 

    it "creates a new current list" do 
     List.stub(:create).with(:user_id=>1,:name => "master") 
     List.should_receive(:create).with(:user_id=>1,:name => "current") 
     @user = User.create 
    end 
    end 
end 

虽然这是真正的风格的问题,这让在这里使用一个真正的用户对象更有意义而不是工厂,因为你正在测试模型本身。

2

zetetic的答案很棒,但如果你想要更快一点的东西(并且仍然有效),我建议使用shoulda-callback-matchers gem。这是一套完整的匹配器,使测试回调更容易。我全部都是关于简化&减少样板。如果你喜欢看,你可以在我的RSpec model testing skeleton中看到一些例子。

无论哪种方式完成工作!