如何使用查找和日期条件进行测试?

时间:2013-01-25 16:33:36

标签: ruby-on-rails-3 unit-testing rspec mocking tdd

我正在尝试为一个方法开发一些测试,该方法负责检索在某个日期之后创建的一些用户。我不知道如何模拟它的测试。方法如下:

def user_list
  render :nothing => true, :status => 422 if params[:time_param].blank?

  time = Time.parse(params[:time_param])
  @users = User.find(:all, :select => 'id, login, email',
                           :conditions => ["created_at > ?", time])
  render :json => { :users => @users }
end

这是我的规范:

describe UsersController do
  context "when receiving time parameter" do
    before (:each) do
      @time_param = "2013-01-25 00:01:00"
      user1 = mock_model(User, :created_at => Time.parse('2013-01-25 00:00:00'))
      user2 = mock_model(User, :created_at => Time.parse('2013-01-25 00:01:00'))
      user3 = mock_model(User, :created_at => Time.parse('2013-01-25 00:02:00'))

      @users = []
      @users << user1 << user2 << user3
    end

    it "should retrieve crimes after 00:01:00 time" do
      User.stub(:find).with(:all, :select => 'id, login, email').and_return(@users)
      get :user_list, { :time_param => @time_param }
      JSON.parse(response.body)["users"].size.should eq 1
    end
  end
end

问题在于它总是返回所有用户,尽管只返回一个用户。 (最后一个)。我在哪里误会?

帮帮我=)

2 个答案:

答案 0 :(得分:1)

你没有测试你在那里测试的东西,在一个控制器规范上,你只需要测试你想要的方法是用你想要的参数调用的,在你的情况下,你必须测试用户模型接收:使用参数查找:all,:select =&gt; 'id,login,email',:conditions =&gt; [“created_at&gt;?”,time](随时间变化应该存在的值。

此外,该逻辑不属于控制器,你应该在User上有一个类方法,比如select_for_json(date)来包装find方法(你可以为它找到一个更好的名字)

然后您的控制器变为:

def user_list
  render :nothing => true, :status => 422 if params[:time_param].blank?

  time = Time.parse(params[:time_param])
  @users = User.select_for_json(time)
  render :json => { :users => @users }
end

你的规范将是

before(:each) do
  @users = mock(:users)
  @time_param = "2013-01-25 00:01:00"
end

it "retrieve users for json" do
  User.should_receive(:select_for_json).once.with(@time).and_return(@users)
  get :user_list, { :time_param => @time }
  assigns(:users).should == @users
end

通过这种方式,您可以确保您的操作能够正常运行,并且规范因为您没有创建用户而速度更快

然后你可以在模型规范上测试该方法,你必须创建一些用户,调用该方法并检查返回的用户(不要在模型规范上存根/模拟任何东西)

答案 1 :(得分:0)

您的stub来电告诉find忽略它应该执行的操作并返回@users。它不会尝试匹配条件。

不幸的是,为了进行测试,我认为您将不得不允许find通过您的数据库执行,这意味着您无法使用mock_model。您可能希望执行User.create(...)FactoryGirl.create(:user)(或其他一些工厂/夹具)。

当然这样做,如果您使用MassAssignmentattr_accessible,则可能会遇到attr_protected个问题,但这些问题很容易stub出来。

我希望有所帮助。