设计会话中的Rspec测试错误#create

时间:2016-12-26 10:56:28

标签: ruby-on-rails ruby rspec devise

我实施了积分系统。登录时,User.point增加2。 我的设计会话控制器如下。

     class Users::SessionsController < Devise::SessionsController
            after_action :add_point, only: [:create]
             # POST /resource/sign_in
             def create
               super
             end
            private

          def add_point
              resource.rewards.create(point: 2)
         end

      end

和我的spec / controllers / users_controller_spec.rb在下面。

RSpec.describe UsersController, type: :controller do
 describe 'adds 2 point with login' do
  before do
      @user=create(:user)
  end
  it 'adds 2 point in one day if two times login' do
    expect{login_user(@user)}.to change {@user.points}.by(0)
  end
  it 'adds 4 point in two day ' do
    expect{login_user(@user)}.to change {@user.points}.by(2)
  end
 end 
end

我的model / user.rb在下面。

      class User < ActiveRecord::Base
             def points
              self.rewards.sum(:point)
             end
      end

当我执行rspec命令时,我遇到了这个错误。

    Failure/Error: expect{login_user(@user)}.to change {@user.points}.by(2)
   expected result to have changed by 2, but was changed by 0

我确认在rails / console中@ user.points增加了2。 为什么我有这个错误?请告诉我。

  
    

通过查看答案,我将其更改为以下。

  
      require 'rails_helper'

      RSpec.describe Users::SessionsController, type: :controller do
       describe 'adds 2 point with login' do
         before do
          @user=create(:user)
          @request.env["devise.mapping"] = Devise.mappings[:user]
        end
        it 'adds 2 point in one day if two times login' do
         expect{post :create, params: {email: @user.email ,password: @user.password} }.to change {@user.points(true)}.by(0)
  end
        it 'adds 4 point in two day ' do
          expect{post :create, params: {email: @user.email ,password: @user.password} }.to change {@user.points(true)}.by(2)
       end
     end
    end

2 个答案:

答案 0 :(得分:1)

首先,您是否配置了路由,因为您使用的是自定义控制器(虽然它继承自Devise Session控制器)?

类似的东西,但在你的情况下,它是会话而不是注册:

devise_for :users, :controllers => { :registrations => "registrations" }

来源: https://howilearnedrails.wordpress.com/2013/12/27/how-to-override-and-customize-the-devise-controller-in-rails/comment-page-1/

其次,由于您基本上使用自定义控制器,请尝试以正常方式命中控制器,而不是使用Devise测试助手。 假设您从下面的Devise文档中获得了login_user方法:

module ControllerMacros   
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user)
      user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
      sign_in user
    end
  end
end

您必须了解login_user方法不会向您创建的Users :: SessionsController发出请求。这就是您的回调after_action :add_point, only: [:create]未被触发的原因,因此没有任何积分被添加到logged_in用户。

通过使用正确的请求命中rspec我的意思是这样调用:

post :create, params: { session_params }

答案 1 :(得分:0)

在大多数情况下都可行:

expect{ login_user(@user) }.to change { @user.reload.points }.by(0)

看起来@user实例与DB失去同步。