2010-08-06 4 views
1

Dans le monde .net, mes spécifications suivraient le pattern Arranger, Act, Assert. J'ai du mal à reproduire cela dans rspec, car il ne semble pas y avoir une possibilité de vérifier sélectivement vos mocks après que le SUT ait pris ses mesures. Cela, couplé avec le fait que TOUTES les attentes sont évaluées à la fin de chaque bloc 'It', me pousse à me répéter dans beaucoup de mes spécifications.DRY le SUT up - question RSpec et Mocking

Voici un exemple de ce que je parle:

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 

Dans cet exemple partiel, je teste la méthode find_new_ideas. Mais je dois l'appeler pour chaque spécification (la spécification complète a 9 blocs d'assertion). Je dois en outre dupliquer la fausse configuration pour qu'elle soit bloquée dans le bloc before, mais attendue individuellement dans le bloc it/assertion. Je duplique ou presque dupliquer une tonne de code ici. Je pense que c'est encore pire que la surbrillance l'indique, car beaucoup de ces globaux ne sont définis que séparément, de sorte qu'ils peuvent être consommés par un test 'attend' plus tard. Y a-t-il un meilleur moyen que je ne vois pas encore?

(SUT = système sous test. Je ne sais pas si c'est ce que tout le monde appelle, ou tout simplement les gens ALT.NET)

Répondre

1

vous pouvez utiliser des groupes d'exemple partagés pour réduire le double emploi:

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 

Une autre technique consiste à utiliser des macros, ce qui est pratique si vous avez besoin sp similaire ecs dans différentes classes.

Remarque: l'exemple ci-dessus est emprunté au , chapitre 12.