【问题标题】:How to configure integration test for PayPal Express Checkout using TestUnit in a Rails 2.3 app如何在 Rails 2.3 应用程序中使用 TestUnit 为 PayPal Express Checkout 配置集成测试
【发布时间】:2013-10-23 15:52:23
【问题描述】:

我们正在添加 PayPal Express Checkout 作为签出在 Rails 2.3.18 上运行的电子商务应用的选项。我已经为我的自定义 PayPal::Merchant::ExpressCheckout 模块完成了代码工作和一些单元测试,但是我无法理解如何正确模拟或存根控制器方法,以便我可以编写集成测试。

我面临的一个问题是所有 PayPal API 调用都指向同一个端点 URI,在 POST 数据中只有一个操作参数来区分我们正在调用的操作。虽然我已成功设置 FakeWeb 以在我的单元测试中模拟来自 PayPal API 的正确 XML 响应,但在某些集成场景中,我需要能够处理背靠背的 API 请求。有没有办法告诉 FakeWeb 根据发布的数据做出不同的响应?或者,有没有办法让 FakeWeb 在拦截第一个请求后触发回调方法,以便我可以设置下一个请求?

另一个问题是如何模拟到 PayPal 的重定向。现在,用户单击我们网站上的 Checkout With PayPal 按钮,该按钮将他们重定向到我的 ExpressCheckoutsController 上的 setup 方法,该方法获取令牌并设置结帐 URL,然后将用户重定向到那里。我需要在集成测试中模拟两个场景: 1.用户正确提交表单并发送到我的返回URL 2. 用户取消并被发送到我的取消 URL 有没有办法在不重写测试文件中的整个 ExpressCheckoutsController 类的情况下做到这一点?

以防万一,我们使用的是 paypal-sdk-merchant gem。我们的测试环境使用以下 gem:

group :test do
  gem 'autotest-rails', '4.1.0'
  gem 'ZenTest', '< 4.6'
  gem 'fakeweb', '1.2.6'
  gem 'mocha', '0.9.4'
  gem 'quietbacktrace', '0.1.1'
  gem 'factory_girl', '1.2.0'
  gem 'thoughtbot-shoulda', '2.10.2', :require => 'shoulda'
  gem 'nokogiri', '1.5.6'
  gem 'webrat', '0.4.4'
end

更新

我能够通过使用 Mocha 来存根我的自定义 ExpressCheckout 模块的 express_checkout_url 方法来解决重定向问题,以便它简单地重定向到 returncancel 操作。

PayPal::Merchant::ExpressCheckout.any_instance.stubs(:express_checkout_url).returns(return_order_express_checkout_path)

【问题讨论】:

    标签: paypal integration-testing ruby-on-rails-2 testunit


    【解决方案1】:

    我了解到 FakeWeb 支持rotating responses,虽然这有助于一些集成测试步骤,但我仍然遇到GetExpressCheckoutDetails API 方法在SetExpressCheckout 和@987654325 之间被调用的次数不确定的情况@ 调用,取决于其他几个因素。我没有试图弄清楚我需要伪造多少响应,而是在挖掘了很多 PayPal::SDK::Core 库之后,我最终在我的集成测试类中使用了这个辅助方法:

    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
    

    这很难看,而且我不喜欢依赖这么多内部 PayPal::SDK::Core 方法来存根我的模块方法,但在我尝试的 2 打方法中,这是最终奏效的方法。

    【讨论】:

    • 你有 set.xml、get.xml 和 do.xml 的例子吗?我喜欢你的解决方案!
    • 自从我最初发布我的解决方案以来,我已经显着更新了我的测试。这是所有活动部件的要点。 gist.github.com/chrisbloom7/51e1471f910f6f692684
    猜你喜欢
    • 2013-11-14
    • 2012-11-23
    • 2014-02-07
    • 2012-10-10
    • 2015-12-14
    • 2017-10-20
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    相关资源
    最近更新 更多