Спецификация контроллера Rspec утверждает, что функция не вызывается - PullRequest
0 голосов
/ 19 сентября 2019

Я тестирую один из моих контроллеров и безуспешно пытался остановить вызов функции.Вот функция:

def fetch_typeform_response
    hp = HealthProfile.find(params[:id])
    form = TypeformService.new('x')
    response = form.getResponse("query=#{ hp[:id] }")

    if response['total_items'] != 1
        if response[:response_id].present?
            response = form.getResponse("included_response_ids=#{ hp[:response_id] }")
        end
    end

    if response['total_items'] == 1

        response = response['items'].first
        health_profile = HealthProfile.map_typeform_response(response)

        if health_profile.save
            health_profile.reload
            redirect_to health_profile_path(health_profile), notice: "Successfully updated the health profile response."
            return
        end

    end

    redirect_to health_profiles_path, notice: "We could not locate the health profile."
end

В моем тесте я заглушаю :getResponse и :map_typeform_response, поскольку они задействуют внешний API:

it "expects to fetch typeform response" do
  new_hp = build(:health_profile)
  new_hp_after_mapping = build(:health_profile)

  allow_any_instance_of(TypeformService).to receive(:getResponse).and_return({ 'total_items': 1, 'items': [ new_hp ] }.as_json)
  allow_any_instance_of(HealthProfile).to receive(:map_typeform_response).and_return(new_hp_after_mapping)

  get :fetch_typeform_response, params: { id: @hp.id }
  expect(response).to redirect_to(health_profile_path(@hp.id))
end

Но я получаю ошибку:HealthProfile does not implement #map_typeform_response.

Если я удаляю заглушку, я вижу ошибку:

Failure/Error: p "Using health_profile_id: #{response['hidden']['id']}"

     NoMethodError:
       undefined method `[]' for nil:NilClass

, которая происходит внутри функции :map_typeform_response (так ясно, что она вызывается!).Есть идеи, почему это может произойти?

1 Ответ

1 голос
/ 19 сентября 2019

Вы вызываете метод map_typeform_response в классе HealthProfile, а не в экземпляре класса.

изменить

allow_any_instance_of(HealthProfile).to receive(:map_typeform_response).and_return(new_hp_after_mapping)

на

allow(HealthProfile).to receive(:map_typeform_response).and_return(new_hp_after_mapping)

Это происходит потому, что rspec не позволяет вам высмеивать или заглушать метод, который не существует на реальном объекте.По умолчанию установлено значение true, так как Rails 4.

RSpec.configure do |config|
  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
end

Некоторые другие рекомендации

Я также рекомендовал бы переместить построение переменных new_hp и new_hp_after_mapping в let

let(:new_hp) { build(:health_profile) }
let(:new_hp_after_mapping) { build(:health_profile) }

переместите заглушки на before

before do
  allow_any_instance_of(TypeformService).to receive(:getResponse).and_return({ 'total_items': 1, 'items': [ new_hp ] }.as_json)
  allow(HealthProfile).to receive(:map_typeform_response).and_return(new_hp_after_mapping)
end

, чтобы ваш тест выглядел как

it "expects to fetch typeform response" do
  # make sure variable @hp intialized in your test.
  get :fetch_typeform_response, params: { id: @hp.id }
  expect(response).to redirect_to(health_profile_path(@hp.id))
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...