在RSpec控制器规范中重构模拟

时间:2011-12-04 16:10:37

标签: ruby ruby-on-rails-3 testing rspec mocking

我有TopicsControllernew动作:

def new
  @section = Section.find(params[:section_id])
  @topic = @section.topics.build
end

在尝试测试这个简单的行为时,我最终得到了非常丑陋且强大的模拟结构

describe "#new" do
  it "builds a topic with a given section" do
    new_topic = mock_model(Topic)
    topics = mock('topics')
    topics.should_receive(:build).and_return(new_topic)

    section = mock_model(Section)
    section.should_receive(:topics).and_return(topics)

    Section.should_receive(:find).with("1").and_return(section)
    get :new, :section_id => 1

    assigns[:topic].should == new_topic
  end
end

我想让这段代码更简单,但我不知道如何。我无法摆脱@section模拟,并且必须在链接.topics.build调用中返回特定内容以允许我设置期望。

有没有更简单的方法呢?我正在使用RSpec 2.7。

2 个答案:

答案 0 :(得分:4)

describe TopicsController do
  specify :new do
    section = stub_chain(:topics, :build).and_return(:new_topic)
    Section.should_receive(:find).with(1).and_return(section)

    get :new, section_id: 1

    assigns_should_match section: section, topic: :new_topic
  end
end

def assigns_should_match(h)
  h.each { |k,v| assigns[k].should == v }
end

答案 1 :(得分:-4)

当你发现时,控制器规格是不必要的痛苦。而不是这样,写一个Cucumber场景(有真实的对象,而不是模拟)。