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.
精彩评论