WedX - журнал о программировании и компьютерных науках

Как настроить интеграционный тест для PayPal Express Checkout с помощью TestUnit в приложении Rails 2.3

Мы находимся в процессе добавления PayPal Express Checkout в качестве опции для проверки из приложения ecom, работающего на Rails 2.3.18. У меня есть рабочий код и несколько модульных тестов для моего пользовательского модуля PayPal::Merchant::ExpressCheckout, но я не понимаю, как правильно имитировать или заглушать методы контроллера, чтобы я мог писать интеграционные тесты.

Одна проблема, с которой я столкнулся, заключается в том, что все вызовы API PayPal относятся к одному и тому же URI конечной точки с только параметром действия в данных POST, чтобы различать, какое действие мы вызываем. Хотя я успешно настроил FakeWeb для имитации правильных ответов XML от PayPal API в своих модульных тестах, есть несколько сценариев интеграции, в которых мне нужно иметь возможность обрабатывать параллельные запросы API. Есть ли способ заставить FakeWeb реагировать по-разному в зависимости от отправленных данных? В качестве альтернативы, есть ли способ заставить FakeWeb вызывать метод обратного вызова после перехвата первого запроса, чтобы я мог настроить следующий запрос?

Другая проблема заключается в том, как смоделировать перенаправление на PayPal. Прямо сейчас пользователь нажимает кнопку «Оформить заказ через PayPal» на нашем сайте, которая перенаправляет его к методу setup на моем ExpressCheckoutsController, который получает токен и устанавливает URL-адрес оформления заказа, а затем перенаправляет пользователя туда. Мне нужно смоделировать два сценария в моих интеграционных тестах: 1. Пользователь правильно отправляет форму и отправляется на мой обратный URL-адрес 2. Пользователь отменяет и отправляется на мой URL-адрес отмены. Есть ли способ сделать это, не переписывая весь ExpressCheckoutsController класс в тестовом файле?

Если это имеет значение, мы используем гем paypal-sdk-merchant. В нашей тестовой среде используются следующие драгоценные камни:

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, чтобы заглушить метод express_checkout_url моего пользовательского модуля ExpressCheckout, чтобы он просто перенаправлял на действия return или cancel.

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

Ответы:


1

Я узнал, что FakeWeb поддерживает повторяющиеся ответы, и пока это помог на некоторых этапах интеграционного теста, я все еще сталкивался со случаями, когда метод GetExpressCheckoutDetails API вызывался неопределенное количество раз между вызовами SetExpressCheckout и DoExpressCheckoutPayment, в зависимости от нескольких других факторов. Вместо того, чтобы пытаться выяснить, сколько ответов мне нужно будет подделать, и после того, как я покопался в большом количестве библиотеки 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 десятков подходов, которые я пробовал, этот, наконец, сработал.

24.10.2013
  • У вас есть примеры set.xml, get.xml и do.xml? Мне нравится ваше решение! 21.06.2014
  • Я значительно обновил свои тесты с тех пор, как изначально опубликовал свое решение. Вот суть со всеми движущимися частями. gist.github.com/chrisbloom7/51e1471f910f6f692684 21.06.2014
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]