1

我是 rspec 的新手,我遇到了一些问题。有人可以帮助我吗?

我有一个负责停用用户的控制器操作。我试图用 rspec 测试来覆盖它,但结果不是我正在等待的。

控制器:

def deactivate
  @user = User.find(params[:id])
  if !@user.nil?
    @user.update_attribute(:active, false)
    redirect_to users_url
  end
end

控制器规格

describe "PUT #deactivate" do
  describe "with valid parameters" do
    before (:each) do
      @user = mock_model(User, :id => 100, :login => "login", :password => "password123",
                               :email => "email@gmail.com", :active => true)
      User.should_receive(:find).with("100").and_return(@user)
    end

    it "should deactivate an user" do
      @user.stub!(:update_attribute).with(:active, false).and_return(true)
      put :deactivate, :id => "100"
      @user.active.should eq false
    end
  end
end

测试结果:

1) UsersController PUT #deactivate with valid parameters should deactivate an user
   Failure/Error: @user.active.should eq false

   expected: false
        got: true

   (compared using ==)

所以,我不明白为什么 active 属性在应该为假时仍然为真。有任何想法吗 ?

谢谢!

4

5 回答 5

1

您似乎不必要地存根 update_attribute 方法。尝试删除该行,看看会发生什么。

于 2012-11-12T17:09:35.183 回答
0

您的期望是“错误的”。

让我们看看it "should deactivate an user"执行您的规范时会发生什么:

  1. @user.stub!(:update_attribute).with(:active, false).and_return(true)修改现有的模拟模型,所以它有一个update_attributewhich,当用参数调用时:activefalse
    1. 将返回true
    2. 将跟踪此调用已发生(这就是模拟所做的)
    3. (并且,与真实User物体不同,不会做任何其他事情
  2. put :deactivate, :id => "100"deactivate在你的控制器中调用真实的
  3. 您的控制器调用User.find. 但是您已经模拟了该类方法,它将返回模拟对象@user,而不是使用 that 搜索实际用户id
  4. 您的控制器调用@user.update_attribute. 但是由于上面的第 3 步,@user这里也是模拟对象。它的update_attributes方法是第 1 步中的方法。正如我们在上面看到的,它将返回 true,跟踪此调用是否发生,并且什么也不做。这意味着它不会改变@user' 的active属性,所以保持true

更改active何时update_attribute调用是实际User类的对象的功能,但在运行规范时没有这样的对象发挥作用。由于此功能继承自ActiveRecord,因此您不必对其进行测试。相反,只需测试update_attribute模拟对象是否已接收到:

    it "should deactivate an user" do
      @user.stub!(:update_attribute).with(:active, false).and_return(true)
      put :deactivate, :id => "100"
      @user.should have_received(:update_attribute).with(:active, false)
    end

(我在这里猜测旧should语法,基于它是如何使用新expect语法完成的。)

嘲笑还是不嘲笑?

如果您确实想测试控制器与实际User实现的组合功能,请不要模拟User或其对象。而是使用request spec从浏览器的角度进行测试。(即使您希望仅针对控制器(模拟模型)和仅针对模型(可能不需要双打,可能对于其他模型除外)进行隔离测试,另外这样做可能是有意义的。

于 2014-12-23T16:16:52.297 回答
0

这个找了好久, update_column 不管你用let还是用都可以build

于 2016-08-26T16:47:03.600 回答
-1

你可以试试这个:

describe "should deactivate an user" do
  before do
    @user.stub!(:update_attribute).with(:active, false).and_return(true)
    put :deactivate, :id => "100"
  end
  it { @user.active.should eq false }
end
于 2012-11-12T18:40:26.720 回答
-2

当您嘲笑对 的调用时update_attribute,模型将如何改变?

如果您是初学者:不要使用存根和模拟!

首先获得测试方面的一般知识,然后将您的知识扩展到模拟和存根。

于 2012-11-12T17:09:49.817 回答