【问题标题】:How to keep Rails controller RSpec test DRY when introducing a private method?引入私有方法时如何保持 Rails 控制器 RSpec 测试 DRY?
【发布时间】:2012-02-17 11:32:38
【问题描述】:

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

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

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

我知道我们永远不应该直接测试私有方法,而是测试公共接口,然后再测试私有方法。当然,我们希望保持我们的规范干燥,而不是在每个“描述”中重复所有常见的功能规范,对吗?

示例类:

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

如您所见,此规范不是很干燥。

有什么指导吗?

【问题讨论】:

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


    【解决方案1】:

    您只需要发送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 上查看文档:https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples

    【讨论】:

    • 不确定 'shared_examples' 是否适合我的情况,因为在 action1 的每个示例中,我都会执行 'post :action1' 以执行测试。
    • 你只需要在前面添加你的帖子:action
    【解决方案2】:

    你可以使用

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

    请参阅Different ways of code reuse in Rspec

    【讨论】:

      【解决方案3】:

      如果您愿意,可以直接测试常见的东西:将其提取到协作类中,然后测试该类。然后在控制器测试中剔除协作者。

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

      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
      

      【讨论】:

        猜你喜欢
        • 2011-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多