Ruby on rails Rspec存根不';行不通

Ruby on rails Rspec存根不';行不通,ruby-on-rails,ruby,rspec,Ruby On Rails,Ruby,Rspec,我有以下规范来测试控制器方法: context "#create" do it "should redirect when model is valid" do User.stub!(:valid?).and_return(true) post :create, :user => FactoryGirl.attributes_for(:user) response.should redirect_to("/") end it "should render

我有以下规范来测试控制器方法:

context "#create" do
  it "should redirect when model is valid" do
    User.stub!(:valid?).and_return(true)
    post :create, :user => FactoryGirl.attributes_for(:user)
    response.should redirect_to("/")
  end
  it "should render new template when model is invalid" do
    User.stub!(:valid?).and_return(false)
    post :create, :user => FactoryGirl.attributes_for(:user)
    response.should render_template(:new)
  end
end
和控制器本身:

def create
  @user = User.new(params[:user])
  if @user.save
    redirect_to "/", :notice => "User created"
  else
    render "new"
  end
end
非常简单的代码,但不知何故
stub
方法实际上并没有存根,所以第二个规范失败,需要使用
但使用
进行渲染。它只是重定向,就像
valid?
返回true一样


我对Rails这个世界还很陌生。我错过了什么?谢谢。

保存对象时,Rails对类实例调用
valid?
。但是您在类本身上留下了
valid?
。那不行

这里要做的是在正在保存的用户实例上存根
保存
,例如

User.stub(:new){mock_model(User,:save=>true)}

@user=user.new
#@user现在是一个模拟对象

@user.save
#模拟对象返回
true

另一个例子是:

User.stub(:new){mock_model(User,:save=>false)}

@user=user.new
#同样,@user是一个模拟用户


@user.save
#模拟对象返回
false

OMG感谢您提供的实例提示!这就是问题所在。虽然我认为最好是存根低级方法,比如
valid?
。通过这种方式,我将能够重构操作,从say
save
build
create
,而不会破坏功能和测试。当然,在这种情况下并非如此。现在我通过将存根附加到User
User.any\u instance.stub(:valid?)的所有实例,并返回(true)
解决了这个问题。但是你对实例和类的提示是我通常忽略的。只要存根
有效?
而不是
save
,我的论点正好相反:)你关于重构的观点很好,但我们可以扭转这一点——如果ActiveRecord被重构,和
save
不再调用引擎盖下的
valid?
?现在您的测试失败是因为您无法控制库的内部实现。在Dev/test中测试ActiveRecord之前,我们几乎不会在生产环境中切换它,不是吗?:)如果我们在开发/测试中进行测试,那么这将是显而易见的,因为测试将从这一点上失败。所以我们总是可以联系到变更日志或其他东西来找出原因。从我的角度来看,应用程序类很可能会比核心类进行重构。@zettetic:这是一个相当古老的线程,有一个奇怪的问题,关于是否有任何方法可以重置存根本身?应该有一种方法在不同的测试用例中返回不同的值。