【问题标题】:DRY the SUT up - RSpec and Mocking questionDRY the SUT up - RSpec 和 Mocking 问题
【发布时间】:2010-08-06 05:42:52
【问题描述】:

在 .net 世界中,我的规范将遵循 Arrange、Act、Assert 模式。我在 rspec 中复制它时遇到了麻烦,因为在 SUT 采取行动后似乎没有能力选择性地验证您的模拟。再加上每个“It”块的末尾都会评估每个期望,这导致我在很多规范中重复自己。

下面是我所说的一个例子:

describe 'AmazonImporter' do
    before(:each) do
        Kernel.**stubs**(:sleep).with(1)
    end
    # iterates through the amazon categories, and for each one, loads ideas with 
    # the right response group, upserting ideas as it goes
    # then goes through, and fleshes out all of the ideas that only have asins.
    describe "find_new_ideas" do
        before(:all) do
            @xml = File.open(File.expand_path('../amazon_ideas_in_category.xml', __FILE__), 'r') {|f| f.read }
        end

        before(:each) do
            @category = AmazonCategory.new(:name => "name", :amazon_id => 1036682)
            @response = Amazon::Ecs::Response.new(@xml)
            @response_group = "MostGifted"
            @asin = 'B002EL2WQI'
            @request_hash = {:operation => "BrowseNodeLookup", :browse_node_id => @category.amazon_id,
                                                    :response_group => @response_group}
            Amazon::Ecs.**expects**(:send_request).with(has_entries(@request_hash)).returns(@response)
            GiftIdea.expects(:first).with(has_entries({:site_key => @asin})).returns(nil)
            GiftIdea.any_instance.expects(:save)            
        end

        it "sleeps for 1 second after each amazon request" do
            Kernel.**expects**(:sleep).with(1)
            AmazonImporter.new.find_new_ideas(@category, @response_group)
        end

        it "loads the ideas for the given response group from amazon" do
            Amazon::Ecs.**expects**(:send_request).
                with(has_entries(@request_hash)).
                returns(@response)

            **AmazonImporter.new.find_new_ideas(@category, @response_group)**
        end

        it "tries to load those ideas from repository" do
            GiftIdea.expects(:first).with(has_entries({:site_key => @asin}))
            **AmazonImporter.new.find_new_ideas(@category, @response_group)**
        end

在这个部分示例中,我正在测试 find_new_ideas 方法。但是我必须为每个规范调用它(完整的规范有 9 个断言块)。我还必须复制模拟设置,以便在 before 块中存根,但在 it/assertion 块中单独预期。我在这里复制或几乎复制了大量代码。我认为这比突出显示的情况更糟,因为许多这些全局变量只是单独定义的,以便稍后可以通过“预期”测试来使用它们。有没有更好的方法我还没有看到?

(SUT = 被测系统。不确定是不是每个人都这么称呼它,还是只是 alt.net 的人)

【问题讨论】:

    标签: ruby mocking rspec bdd


    【解决方案1】:

    您可以使用共享示例组来减少重复:

    shared_examples_for "any pizza" do
      it "tastes really good" do
        @pizza.should taste_really_good
      end
      it "is available by the slice" do
        @pizza.should be_available_by_the_slice
      end
    end
    
    describe "New York style thin crust pizza" do
      before(:each) do
        @pizza = Pizza.new(:region => 'New York' , :style => 'thin crust' )
      end
    
      it_behaves_like "any pizza"
    
      it "has a really great sauce" do
        @pizza.should have_a_really_great_sauce
      end
    end
    

    另一种技术是使用宏,如果您需要不同类中的类似规范,这很方便。

    注意:上面的例子是从The RSpec Book,第12章借来的。

    【讨论】:

      【解决方案2】:

      如果有帮助,您可以使用“上下文”将它们分开...

      https://github.com/dchelimsky/rspec/wiki/faq

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-08
        • 1970-01-01
        • 1970-01-01
        • 2019-01-08
        相关资源
        最近更新 更多