I learned that FakeWeb supports rotating responses, and while this helped in some integration test steps, I was still running into instances where GetExpressCheckoutDetails
API method would be called an indeterminate number of times between the SetExpressCheckout
and DoExpressCheckoutPayment
calls, depending on several other factors. Rather than try to figure out how many responses I would need to fake, and after digging through a lot of the PayPal::SDK::Core
library, I ended up with this helper method in my integration test class:
def stub_express_checkout
api = PayPal::SDK::Merchant::API.new
PayPal::Merchant::ExpressCheckout.any_instance.stubs(:express_checkout_url).returns(return_order_express_checkout_path)
FakeWeb.register_uri(
:post,
api.service_endpoint,
:content_type => "application/xml",
:status => ["200", "OK"],
:body => ""
)
PayPal::Merchant::ExpressCheckout.any_instance.stubs(:set_express_checkout).returns(
PayPal::SDK::Merchant::DataTypes::SetExpressCheckoutResponseType.new(api.format_response({
:response => FakeWeb.response_for(:post, api.service_endpoint).tap { |resp|
resp.instance_variable_set("@body", File.read(Rails.root.join("test/fixtures/express_checkout/success/set.xml")))
}
})[:data])
)
PayPal::Merchant::ExpressCheckout.any_instance.stubs(:get_express_checkout).returns(
PayPal::SDK::Merchant::DataTypes::GetExpressCheckoutDetailsResponseType.new(api.format_response({
:response => FakeWeb.response_for(:post, api.service_endpoint).tap { |resp|
resp.instance_variable_set("@body", File.read(Rails.root.join("test/fixtures/express_checkout/success/get.xml")))
}
})[:data])
)
PayPal::Merchant::ExpressCheckout.any_instance.stubs(:do_express_checkout).returns(
PayPal::SDK::Merchant::DataTypes::DoExpressCheckoutPaymentResponseType.new(api.format_response({
:response => FakeWeb.response_for(:post, api.service_endpoint).tap { |resp|
resp.instance_variable_set("@body", File.read(Rails.root.join("test/fixtures/express_checkout/success/do.xml")))
}
})[:data])
)
FakeWeb::Registry.instance.uri_map[FakeWeb::Registry.instance.send(:normalize_uri, api.service_endpoint)] = {}
end
It's ugly, and I don't like having to rely on so many internal PayPal::SDK::Core
methods to stub my modules methods, but out of the 2 dozen approaches I tried, this is the one that finally worked.