代码之家  ›  专栏  ›  技术社区  ›  oma

模型中的RSpec mock或stub super

  •  3
  • oma  · 技术社区  · 15 年前

    如何使用super测试模块的这一小部分?(超类是action_dispatch-3.0.1测试/集成…)模块包含在规范/拦截请求中 邮递 :

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

    我不想让它运行ActionDispatch::集成,但我不知道 how to mock or stub super 进行单元测试。

    该模块只在规范中使用,并且将具有100%的测试覆盖率,这证明了这些类型的度量是无用的。我需要对它进行单元测试。

    一个例子,如果需要的话,这就是我如何使用ApiDoc模块

    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
    
    2 回复  |  直到 12 年前
        1
  •  4
  •   Petrik de Heus    15 年前

    您可以检查是否对“super”类调用了该方法

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

    由于ApiDock仅对测试是必需的,因此您还可以使用alias_method_chain覆盖post方法:

    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
    
        2
  •  1
  •   oma    15 年前

    这只是对答案的补充。我就是这样测试的

    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,但是我仍然无法用我的虚拟类规范来实现这一点。