Как заглушить метод для класса, сгенерированного во время выполнения с помощью минитеста Rails?

Я хочу заглушить вызов стороннего компонента, но найти это довольно сложно в мини-тесте Rails. Я начну с самого основного вопроса выше. Вот очень упрощенный псевдокод, чтобы лучше объяснить, что я пытаюсь сделать:

class RequestController < ActionController::Base
  def schedule
    # Parse a bunch of params and validate

    # Generate a unique RequestId for this request

    # Save Request stuff in the DB

    # Call 3rd party scheduler app to queue request action
    scheduler = Scheduler.new
    submit_success = scheduler.submit_request

    # Respond to caller
   end
 end

Итак, я пишу интеграционные тесты для RequestController и хочу заглушить вызов 'scheduler.submit_request'. Мой тестовый код выглядит примерно так:

def test_schedule_request
  scheduler_response = 'Expected response string for RequestId X'
  response = nil
  Scheduler.stub :submit_request, scheduler_response do
    # This test method calls the RequestController schedule route above
    response = send_schedule_request(TEST_DATA)
  end

  # Validate (assert) response
end

Кажется довольно простым, но, видимо, я не могу заглушить метод для класса, которого (пока) не существует. Итак, как мне заглушить метод класса для объекта, созданного во время выполнения, в коде, который я тестирую?


person Gusto    schedule 19.11.2013    source источник


Ответы (2)


Я не уверен насчет минитеста. Но в rspec вам также придется заглушить часть инициализации и вернуть имитированный объект планировщика.

Вот как я бы сделал это в rspec.

mock_scheduler = double("scheduler")
Scheduler.stub(:new).and_return(mock_scheduler)
mock_scheduler.stub(:submit_request).and_return(response)

Другим вариантом будет

   Scheduler.any_instance.stub(:submit_request).and_return(response)
person usha    schedule 19.11.2013

Как заметил Вимша, вы должны сначала заглушить инициализацию класса. Мне не удалось заставить его код работать, но приведенный ниже пересмотренный тестовый код имеет ту же идею:

def test_schedule_request
  scheduler_response = 'Expected response string for RequestId X'
  response = nil
  scheduler = Scheduler.new
  Scheduler.stub :new, scheduler do
    scheduler.stub :submit_request, scheduler_response do
      # This test method calls the RequestController schedule route above
      response = send_schedule_request(TEST_DATA)
    end
  end

  # Validate (assert) response
end

Спасибо, Дэйв

person Gusto    schedule 20.11.2013