2010-11-26 7 views
3

スーパーのモジュールのこの小さな部分をテストするにはどうすればよいですか?RSpecモックまたはスタブをモデルにスーパー

module ApiDoc 
    def post(path, parameters = nil, headers = nil) 
    super 
    document_request("post", path, parameters, headers) if ENV['API_DOC'] == "true" 
    end 
    ... 
end 

私はそれがActionDispatchを実行したくない::統合 - :モジュールはポストを傍受する仕様/要求に含まれている(スーパークラスは... action_dispatch-3.0.1テスト/統合です)何でも、私はそれをテストするためにhow to mock or stub superを知らない。

モジュールは仕様内でのみ使用され、100%のテストカバレッジを持つため、このようなメトリックは役に立たないと証明されます。私はそれをユニットテストする必要があります。

例は、必要であれば、これは私がApiDockだけなので

require 'spec_helper' 

describe "Products API" do 
    include ApiDoc ############## <---- This is my module 
    context "POST product" do 
    before do 
     @hash = {:product => {:name => "Test Name 1", :description => "Some data for testing"}} 
    end 

    it "can be done with JSON" do 
     valid_json = @hash.to_json 
     ############### the following 'post' is overriden by ApiDoc 
     post("/products.json",valid_json, 
     {"CONTENT_TYPE" => "application/json", 
     "HTTP_AUTHORIZATION" => ActionController::HttpAuthentication::Basic.encode_credentials("user", "secret")}) 
     response.should be_success 
    end 
    end 
end 

答えて

4

あなたは「スーパー」クラス

ActionDispatch::Integration.any_instance.should_receive(:post) 

にメソッドが呼び出されたかどうかを確認することができ、モジュールApiDocを使用する方法でありますあなたのテストに必要なら、postメソッドをalias_method_chainで上書きすることもできます:

ActionDispatch::Integration.instance_eval do 
    def post_with_apidoc(path, parameters = nil, headers = nil) 
    post_without_apidoc 
    if ENV['API_DOC'] == "true" 
     document_request("post", path, parameters, headers) 
    end 
    end 
    alias_method_chain :post, :apidoc 
end 
+0

ありがとうございます!私はmochaを使っているので、これはうまくいきます: 'ActionDispatch :: Integration :: Session.any_instance.expects(:post).with xx'ですが、私はApiDoc.postまたは-.document_requestをモックできません。そのクラス(ApiDocの)は 'RSpec :: Core :: ExampleGroup :: Nested_1'ですこの場合、これらのメソッドをどうやって模倣するのですか?または、その動作をテストするために、ダミーのクラスを作成してそれをインクルードするのですか? – oma

+0

ダミークラスを作成する方が良い選択肢だと思います。 –

+0

最初のコード行のために受け入れられた答え。ダミークラスのユニットテストは良い考えです。 FYIでは、 'super'を使用する方がエイリアスメソッドチェーンよりも優先されます。これらのエイリアスは、レール2.xを3にリファクタリングするときに、このようなエイリアスをたくさん削除しました。 – oma

1

これはiです単に答えに対する補足物です。これで私はそれをテストし終わったのです。

require 'spec_helper' 

describe 'ApiDoc' do 
    include ApiDoc 

    it "should pass the post to super, ActionDispatch" do 
    @path = "path" 
    @parameters = {:param1 => "someparam"} 
    @headers = {:aheader => "someheaders"} 
    ActionDispatch::Integration::Session.any_instance.expects(:post).with(@path, @parameters, @headers) 
    post(@path, @parameters, @headers) 
    end 
end 

class DummySuper 
    def post(path, parameters=nil, headers=nil) 
    #How to verify this is called? 
    end 
end 
class Dummy < DummySuper 
    include ApiDoc 
end 

describe Dummy do 

    it "should call super" do 
    subject.expects(:enabled?).once.returns(true) 
    #how to expect super, the DummySuper.post ? 
    path = "path" 
    parameters = {:param1 => "someparam"} 
    headers = {:aheader => "someheaders"} 
    subject.expects(:document_request).with("post", path, parameters, headers) 
    subject.post(path, parameters, headers) 
    end 
end 

とわずかに改変されたApiDocです。

module ApiDoc 
    def enabled? 
    ENV['API_DOC'] == "true" 
    end 

    def post(path, parameters = nil, headers = nil) 
    super 
    document_request("post", path, parameters, headers) if enabled? 
    end 

private 
    def document_request(verb, path, parameters, headers) 
    ... 
    end 
end 

私は最初のテストでsuper.postを確認することができ、私はまだ私のダミークラスの仕様で、まさにそれを行う方法を見つけ出すことはできません。

関連する問題