开发者

RSpec mock or stub super in a model

How do I test this tiny part of the module, with super? (superclass is action_dispatch-3.0.1 testing/integration...) The module is included within spec/requests to intercept post:

module ApiDoc
  def post(path, parameters = nil, headers = nil)
    super
    document_request("post"开发者_如何学C, path, parameters, headers) if ENV['API_DOC'] == "true"
  end
  ...
end

I don't want it to run the ActionDispatch::Integration-whatever, but I don't know how to mock or stub super to unit test it.

The module is only used within specs, and will have 100% test coverage, which proves those kinds of metrics as useless. I need to unit test it.

An example, if needed, this is how I use the module 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


You can check if the method is called on the 'super' class

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

Since ApiDock is only required for your tests you could also overwrite the post method with 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


This is merely a supplement to the answer. This is how I ended up testing it

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

and the slightly modified 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

I could verify the super.post in the first test, but I still can't figure out how to do just that with my Dummy class specs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜