2009-10-28 38 views
2

我一直无法找到任何此类情况。我定义它有一个名为范围的模型正是如此:在RSpec控制器中扼杀named_scope

class Customer < ActiveRecord::Base 
    # ... 
    named_scope :active_customers, :conditions => { :active => true } 
end 

和我试图存根它在我的控制器规格:

# spec/customers_controller_spec.rb 
describe CustomersController do 
    before(:each) do 
    Customer.stub_chain(:active_customers).and_return(@customers = mock([Customer])) 
    end 

    it "should retrieve a list of all customers" do 
    get :index 
    response.should be_success 
    Customer.should_receive(:active_customers).and_return(@customers) 
    end 
end 

这不是工作和失败,他说,客户期望active_customers但收到0次。在我的实际控制人索引行动中,我有@customers = Customer.active_customers。我错过了什么让这个工作?可悲的是,我发现编写代码比编写测试/规范更容易,并且写出来,因为我知道规范描述的内容,而不是如何告诉RSpec我想做什么。

回答

8

我认为在stubsmessage expectations中存在一些混淆。消息预期基本上是存根,您可以在其中设置所需的预设响应,但它们也会测试正在测试的代码所进行的调用。相比之下,存根就是对方法调用的罐头响应。但不要在同一个方法和测试中混合一个存根与一个消息期望或不好的事情会发生 ...

回到你的问题,有两件事(或更多?),需要spec'ing在这里:

  1. 那CustomersController调用Customer#active_customers,当你做一个indexget。在本规范中返回Customer#active_customers并不重要。
  2. active_customers named_scope确实返回客户,其中active字段为true

我认为你正在尝试做数字1。如果是这样,删除整个存根和简单地设置在您的测试消息的预期:

describe CustomersController do 
    it "should be successful and call Customer#active_customers" do 
    Customer.should_receive(:active_customers) 
    get :index 
    response.should be_success 
    end 
end 

在你没有什么测试上述规格它返回。这没关系,因为这是规范的目的(尽管你的规范太接近实现而不是行为,但这是一个不同的话题)。如果您想拨打active_customers特别返回某些内容,请继续并将.and_returns(@whatever)添加到该消息期望值中。故事的另一部分是测试active_customers如预期的那样工作(即:实际调用数据库的模型规范)。

Customer.stub_chain(:active_customers).and_return(@customers = [mock(Customer)]) 
+0

谢谢您的解释(我在下面的一个RSpec教程,但是它是如何显示到用模拟/存根执行操作)。然而,当我尝试你发布的代码时,我得到了同样的错误: expected:active_customers(任何参数)一次,但收到0次。尽管在CustomersController#index中调用了Customer.active_customers。 – 2009-10-28 19:57:55

+0

对不起,我的坏。对'get:index'的调用应该在消息期望之后。我正在纠正答案,以便期望成为规范中的第一行。 – hgmnz 2009-10-28 20:45:32

+0

好的,现在正在工作。我习惯于正常的测试过程,get:index在测试之前出现,所以这似乎是问题。它与RSpec相反。我想我需要更多练习RSPec。谢谢! – 2009-10-29 12:50:11

1

,如果你想测试你接收回来的客户记录的数组,像这样你应该有周围的模拟阵列。

我有一个控制器调用

ExerciseLog.this_user(current_user).past.all 

而且我能够存根,像这样

ExerciseLog.stub_chain(:this_user,:past).and_return(@exercise_logs = [mock(ExerciseLog),mock(ExerciseLog)]) 
0

stub_chain已经工作最适合我:

+0

http://apidock.com/rspec/Spec/Mocks/Methods/stub_chain – jspooner 2010-05-28 16:25:07