我无法理解为什么我似乎无法存根此控制器方法:load_user
,因为如果我将:load_user
的实际实现更改为不返回实例,则我的所有测试都会失败@user
。
当RSpec向控制器发出请求时,有人可以看到为什么我的存根(controller.stub!(:load_user).and_return(@user)
)似乎无法实际调用吗?
require 'spec_helper'
describe TasksController do
before(:each) do
@user = Factory(:user)
sign_in @user
@task = Factory(:task)
User.stub_chain(:where, :first).and_return(@user)
controller.stub!(:load_user).and_return(@user)
end
#GET Index
describe "GET Index" do
before(:each) do
@tasks = 7.times{Factory(:task, :user => @user)}
@user.stub!(:tasks).and_return(@tasks)
end
it "should should find all of the tasks owned by a user" do
@user.should_receive(:tasks).and_return(@tasks)
get :index, :user_id => @user.id
end
it "should assign all of the user's tasks to the view" do
get :index, :user_id => @user.id
assigns[:tasks].should be(@tasks)
end
end
#GET New
describe "GET New" do
before(:each) do
@user.stub_chain(:tasks, :new).and_return(@task)
end
it "should return a new Task" do
@user.tasks.should_receive(:new).and_return(@task)
get :new, :user_id => @user.id
end
end
#POST Create
describe "POST Create" do
before(:each) do
@user.stub_chain(:tasks, :new).and_return(@task)
end
it "should create a new task" do
@user.tasks.should_receive(:new).and_return(@task)
post :create, :user_id => @user.id, :task => @task.to_s
end
it "saves the task" do
@task.should_receive(:save)
post :create, :user_id => @user.id, :task => @task
end
context "when the task is saved successfully" do
before(:each) do
@task.stub!(:save).and_return(true)
end
it "should set the flash[:notice] message to 'Task Added Successfully'"do
post :create, :user_id => @user.id, :task => @task
flash[:notice].should == "Task Added Successfully!"
end
it "should redirect to the user's task page" do
post :create, :user_id => @user.id, :task => @task
response.should redirect_to(user_tasks_path(@user.id))
end
end
context "when the task isn't saved successfully" do
before(:each) do
@task.stub(:save).and_return(false)
end
it "should return to the 'Create New Task' page do" do
post :create, :user_id => @user.id, :task => @task
response.should render_template('new')
end
end
end
it "should attempt to authenticate and load the user who owns the tasks" do
context "when the tasks belong to the currently logged in user" do
it "should set the user instance variable to the currently logged in user" do
pending
end
end
context "when the tasks belong to another user" do
it "should set the flash[:notice] to 'Sorry but you can't view other people's tasks.'" do
pending
end
it "should redirect to the home page" do
pending
end
end
end
end
class TasksController < ApplicationController
before_filter :load_user
def index
@tasks = @user.tasks
end
def new
@task = @user.tasks.new
end
def create
@task = @user.tasks.new
if @task.save
flash[:notice] = "Task Added Successfully!"
redirect_to user_tasks_path(@user.id)
else
render :action => 'new'
end
end
private
def load_user
if current_user.id == params[:user_id].to_i
@user = User.where(:id => params[:user_id]).first
else
flash[:notice] = "Sorry but you can't view other people's tasks."
redirect_to root_path
end
end
end
任何人都可以看到为什么我的存根不起作用?就像我说的,我的测试只有在确保load_user工作时才会通过,否则,我的所有测试都会失败,这让我认为RSpec没有使用我创建的存根。
答案 0 :(得分:8)
删除load_user
会破坏你的测试,因为它会破坏方法。当控制器调用load_user
时,它将不再运行您的原始代码。它现在只返回你在and_return(...)
中指定的任何内容(它返回到ActionController
回调堆栈,忽略false
以外的任何内容。
您的控制器代码未使用该方法的返回值;它在中使用变量实例化的。由于未运行load_user
方法的原始代码,因此永远不会实例化@user
实例变量。 (测试中的@user
变量仅对您的测试可见。)
但是对于你拥有的所有其他存根,我认为没有任何理由你根本不需要存根load_user
。只要您将current_user
缩进以返回@user
(我假设是在sign_in
方法中完成),那么就不应该有任何需要。
答案 1 :(得分:2)
您也可以通过执行类似
的断言来验证存根是否正常工作controller.current_user.should == @user