【问题标题】:Scaffold generated rspec controller test returns nil on Factory created model支架生成的 rspec 控制器测试在工厂创建的模型上返回 nil
【发布时间】:2014-04-15 19:22:34
【问题描述】:

即使以下行在模型测试中运行良好:

game = FactoryGirl.create(:game)

games_controller_rspec.rb 上似乎没有。

describe "GET index" do
    it "assigns all games as @games" do
      game = FactoryGirl.create(:game)
      get :index, {}
      expect(assigns(:games)).to eq([game])
    end
end

我不断得到“预期:[...] 得到:无”

这是工厂:

FactoryGirl.define do
  factory :game do |f|
    f.team_a_id { 1 }
    f.team_b_id { 2 }
  end
end

完整的 games_controller.rb:

class GamesController < ApplicationController
before_action :set_game, only: [:show, :edit, :update, :destroy]
before_filter :check_admin_status, only: [:new, :edit, :create, :update, :destroy]

def index
    @games = Game.all
end

def show
end

def new
    @game = Game.new
end

def edit
end

def create
    @game = Game.new(game_params)

respond_to do |format|
    if @game.save
        format.html { redirect_to @game, notice: 'Game was successfully created.' }
        format.json { render action: 'show', status: :created, location: @game }
    else
        format.html { render action: 'new' }
        format.json { render json: @game.errors, status: :unprocessable_entity }
    end
end

结束

def update
    respond_to do |format|
        if @game.update(game_params)
        format.html { redirect_to @game, notice: 'Game was successfully updated.' }
        format.json { head :no_content }
    else
        format.html { render action: 'edit' }
        format.json { render json: @game.errors, status: :unprocessable_entity }
    end
    end

end

def destroy
    @game.destroy
    respond_to do |format|
      format.html { redirect_to games_url }
      format.json { head :no_content }
    end
  end

private
    def set_game
      @game = Game.find(params[:id])
    end

    def game_params
      params.require(:game).permit(:team_a_id, :team_b_id)
    end
end

完整的 games_controller_spec.rb:

require 'spec_helper'

describe GamesController do
  include Devise::TestHelpers

  let(:valid_attributes) { { "team_a_id" => "1" } }
  let(:valid_session) { {} }

  describe "GET index" do
    it "assigns all games as @games" do
      game = FactoryGirl.create(:game)
      get :index, {}
      expect(assigns(:games)).to eq([game])
    end
  end

  describe "GET show" do
    it "assigns the requested game as @game" do
      game = FactoryGirl.create(:game)
      get :show, {:id => game.to_param}, valid_session
      expect(assigns(:game)).to eq(game)
    end
  end

  describe "GET new" do
    it "assigns a new game as @game" do
      get :new, {}, valid_session
      expect(assigns(:game)).to be_a_new(Game)
    end
  end

  describe "GET edit" do
    it "assigns the requested game as @game" do
      game = FactoryGirl.create(:game)
      get :edit, {:id => game.to_param}, valid_session
      expect(assigns(:game)).to eq(game)
    end
  end

  describe "POST create" do
    describe "with valid params" do
      it "creates a new Game" do
        expect {
          post :create, {:game => valid_attributes}, valid_session
        }.to change(Game, :count).by(1)
      end

      it "assigns a newly created game as @game" do
        post :create, {:game => valid_attributes}, valid_session
        expect(assigns(:game)).to be_a(Game)
        expect(assigns(:game)).to be_persisted
      end

      it "redirects to the created game" do
        post :create, {:game => valid_attributes}, valid_session
        expect(response).to redirect_to(Game.last)
      end
    end

    describe "with invalid params" do
      it "assigns a newly created but unsaved game as @game" do
        allow_any_instance_of(Game).to receive(:save).and_return(false)
        post :create, {:game => { "team_a_id" => "invalid value" }}, valid_session
        expect(assigns(:game)).to be_a_new(Game)
      end

      it "re-renders the 'new' template" do
        allow_any_instance_of(Game).to receive(:save).and_return(false)
        post :create, {:game => { "team_a_id" => "invalid value" }}, valid_session
        expect(response).to render_template("new")
      end
    end
  end

  describe "PUT update" do
    describe "with valid params" do
      it "updates the requested game" do
        game = Game.create! valid_attributes
        expect_any_instance_of(Game).to receive(:update).with({ "team_a_id" => "1" })
        put :update, {:id => game.to_param, :game => { "team_a_id" => "1" }}, valid_session
      end

      it "assigns the requested game as @game" do
        game = Game.create! valid_attributes
        put :update, {:id => game.to_param, :game => valid_attributes}, valid_session
        expect(assigns(:game)).to eq(game)
      end

      it "redirects to the game" do
        game = Game.create! valid_attributes
        put :update, {:id => game.to_param, :game => valid_attributes}, valid_session
        expect(response).to redirect_to(game)
      end
    end

    describe "with invalid params" do
      it "assigns the game as @game" do
        game = Game.create! valid_attributes
        allow_any_instance_of(Game).to receive(:save).and_return(false)
        put :update, {:id => game.to_param, :game => { "team_a_id" => "invalid value" }}, valid_session
        expect(assigns(:game)).to eq(game)
      end

      it "re-renders the 'edit' template" do
        game = Game.create! valid_attributes
        allow_any_instance_of(Game).to receive(:save).and_return(false)
        put :update, {:id => game.to_param, :game => { "team_a_id" => "invalid value" }}, valid_session
        expect(response).to render_template("edit")
      end
    end
  end

  describe "DELETE destroy" do
    it "destroys the requested game" do
      game = Game.create! valid_attributes
      expect {
        delete :destroy, {:id => game.to_param}, valid_session
      }.to change(Game, :count).by(-1)
    end

    it "redirects to the games list" do
      game = Game.create! valid_attributes
      delete :destroy, {:id => game.to_param}, valid_session
      expect(response).to redirect_to(games_url)
    end
  end

end

【问题讨论】:

  • 我们需要查看您的控制器代码 - 它实际上是否为视图定义了@games
  • 是的,七海猫:def index @games = Game.all end
  • 你能发布 full 控制器和 full 规范吗?
  • 刚刚做到了。希望对你有帮助

标签: ruby-on-rails ruby rspec factory-bot


【解决方案1】:

找到了。问题在于用户权限。我正在使用设计,只允许普通用户使用某些方法。因此,除非我使用管理员用户进行测试,否则他们的结果将为零。 基本上我必须在规范上设置一个管理员用户才能使其工作。

这就是你的做法:

1) 在 spec/support 中写入 controller_macros.rb

module ControllerMacros
  def login_admin
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:admin]
      sign_in FactoryGirl.create(:admin) # Using factory girl as an example
    end
  end

  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user)
      user.confirm! 
      sign_in user
    end
  end
end

2) 将其添加到 spec_helper

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end

3) 在你的 controller_spec 上将用户设置为管理员

describe GamesController do
    login_admin

    describe "GET index" do
        game = FactoryGirl.create(:game)
        get :index, {}, valid_session
        expect(assigns(:games).to eq([game])
    end

我的用户工厂:

FactoryGirl.define do
    factory :user do
        email "nn@nnn.com"
        password "12345654321"
        password_confirmation { "12345654321" }
        factory :admin do
            after(:create) { |user| user.update_attribute :admin, true }
        end
    end
end

创立here

【讨论】:

    【解决方案2】:

    我也有同样的问题。我在这里找到了一个帖子(我忘了给它加书签,找不到它)说用“controller.index”替换你的“get :index,{}”,看看它是否有效。当我这样做时,它对我有用。他们还说这是一个路由问题。我不明白为什么以及如何修复它,以便我可以使用从脚手架生成的标准代码。我的路由测试通过了,但是有一个路由问题导致“get”在这些测试中不起作用?我不明白。

    编辑:

    刚刚找到帖子。看看here. OP 永远不会回来告诉我们他们是如何解决问题的。我很想知道,因为我很沮丧地试图弄清楚如何让它发挥作用。

    【讨论】:

    • 谢谢,我会检查路由,以防万一。但是将其更改为 controller.index 对我来说并不适用。
    • 对不起,我的错误。这实际上起到了作用。但是路由没问题,所以我真的不知道是什么问题..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    相关资源
    最近更新 更多