RSpec模拟或存根超级模型

时间:2010-11-26 14:59:02

标签: ruby unit-testing module mocking rspec

如何使用super来测试模块的这个微小部分? (超类是action_dispatch-3.0.1测试/集成......)模块包含在规范/请求中以拦截 post

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

我不希望它运行ActionDispatch :: Integration-whatever,但我不知道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 个答案:

答案 0 :(得分:4)

您可以检查是否在“超级”类

上调用该方法
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

答案 1 :(得分:1)

这仅仅是对答案的补充。这就是我最终测试它的方式

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,但我仍然无法弄清楚如何使用我的Dummy类规范来做到这一点。