如何在引入私有方法时保持Rails控制器RSpec测试DRY?

时间:2012-02-17 11:32:39

标签: ruby-on-rails unit-testing rspec

目前,我们在控制器中定义了一个动作,我们使用RSpec进行测试。我们现在需要创建第二个操作,该操作需要重用第一个操作中包含的大部分功能。

因此,我们将这个公共代码重构为私有方法,然后让这两个动作调用私有方法。

问题是,我们在哪里测试这个私有方法的功能?请记住,它正在做很多事情。

我知道我们永远不应该直接测试私有方法,而是测试公共接口,而公共接口又会测试私有方法。当然,我们希望保持我们的规格DRY而不是重复每个'describe'中的所有常用功能规格,我们会吗?

示例类:

class MyController < ApplicationController

    def action1
        ...
        # Do something unique to 'action1'
        ...
        my_object = ...

        do_some_common_stuff(my_object)
    end

    def action2
        ...
        # Do something unique to 'action2'
        ...
        my_object = ...

        do_some_common_stuff(my_object)
    end

    private
    def do_some_common_stuff(my_object)
        # Do something common 1
        # Do something common 2
        # Do something common 3
        # Do something common 4
        # Do something common 5
    end
end

示例测试规范:

describe MyController do
    describe "POST 'action1'" do
        it "should do something unique to action1"

        it "should do something common 1" do
            some_object.should_receive(:a_call)
            post :action1
        end

        it "should do something common 2"
        it "should do something common 3"
        it "should do something common 4"
        it "should do something common 5"
    end

    describe "POST 'action2'" do
        it "should do something unique to action2"

        it "should do something common 1" do
            some_object.should_receive(:a_call)
            post :action2
        end

        it "should do something common 2"
        it "should do something common 3"
        it "should do something common 4"
        it "should do something common 5"
    end
end

正如你所看到的,这个规格不是很干。

任何指导?

3 个答案:

答案 0 :(得分:2)

您只需要shared_examples

shared_examples "common" do
  it "should do something common 1"
  it "should do something common 2"
  it "should do something common 3"
  it "should do something common 4"
  it "should do something common 5"
end

并在您的规范中使用它

describe "POST 'action2'" do
  it_should_behave_like "common"
  it "should do something unique to action2"
end

您可以在rspec上查看文档:{​​{3}}

答案 1 :(得分:2)

您可以使用

  • RSpec帮助方法和模块,或
  • RSpec自定义匹配器,或
  • RSpec共享示例,或
  • RSpec共享上下文

参考Different ways of code reuse in Rspec

答案 2 :(得分:0)

可以直接测试常见的东西,如果你想:将它提取到一个协作类中,并测试该类。然后在控制器测试中删除协作者。

如果您不想这样做,那么共享示例可能是最佳选择。请注意,共享示例实际上是由使用它们的上下文参数化的:

shared_examples "common" do
  it "does something common" do
    subject.should be_whatever
  end
end

describe "POST 'action1'" do
  subject { post :action1 }
  it_behaves_like "common"
end

describe "POST 'action2'" do
  subject { post :action2 }
  it_behaves_like "common"
end