Тест Rspec для проверки заполнения пользователем самостоятельно заполняемого атрибута ip_location (Rails 4/devise/geocoder)

На странице регистрации моего устройства я реализовал функцию отслеживания IP-адресов, которая, когда пользователь регистрируется, отправляет страну, из которой он пришел, чтобы заполнить атрибут только что созданной учетной записи «user_country».

Это работает, но как новичок я не знаю, как проверить с помощью rspec, что это работает, т. е. если я создам пользователя, который зарегистрируется, то ПОСЛЕ создания учетной записи эта страна_пользователя больше не будет пустой.

Вот как я использую метод /app/controllers/registrations_controller.rb для назначения страны вновь созданной учетной записи пользователя на controllers/registrations_controller.rb — см. ниже.

class RegistrationsController < Devise::RegistrationsController

  layout 'lightbox'

  def update     
    account_update_params = devise_parameter_sanitizer.sanitize(:account_update)

    # required for settings form to submit when password is left blank
    if account_update_params[:password].blank?
      account_update_params.delete("password")
      account_update_params.delete("password_confirmation")
    end    
    @user = User.find(current_user.id)
    if @user.update(account_update_params) # Rails 4 .update introduced with same effect as .update_attributes
      set_flash_message :notice, :updated
      # Sign in the user bypassing validation in case his password changed
      sign_in @user, :bypass => true
      redirect_to after_update_path_for(@user)
    else
      render "edit"
    end
  end

  # for Rails 4 Strong Parameters
  def resource_params
    params.require(:user).permit(:email, :password, :password_confirmation, :current_password, :user_country)
  end
  private :resource_params

  protected
    def after_sign_up_path_for(resource)
      resource.update(user_country: set_location_by_ip_lookup.country) #use concerns/CountrySetter loaded by ApplicationController
      root_path
    end  

end

Если это поможет, вот как я нахожу страну посетителя:

module CountrySetter

    extend ActiveSupport::Concern

    included do
        before_filter :set_location_by_ip_lookup 
    end

    # we use geocoder gem
    # output: ip address
    def set_location_by_ip_lookup  
      if Rails.env.development? or Rails.env.test?
        Geocoder.search(request.remote_ip).first
      else
        request.location
      end
    end
end

person Mathieu    schedule 27.07.2014    source источник
comment
Я вижу, вы делаете if Rails.env.development? or Rails.env.test?. Будьте КРАЙНЕ осторожны при использовании литерала and or в Ruby, потому что они предназначены для использования в потоке управления, а не в логических выражениях. Использование их без понимания их побочных эффектов может вызвать серьезные проблемы, например, если выражение всегда возвращает true.   -  person rickypai    schedule 27.07.2014
comment
также and or имеют гораздо более низкий порядок операций, чем && || techotopia.com/index.php/Ruby_Operator_Precedence< /а>   -  person rickypai    schedule 27.07.2014
comment
спасибо за эти советы: я буду осторожен и попытаюсь понять разницу между ANd и && + или против || =› как новичок в Rails, я думал, что это в основном то же самое :) я проверю это   -  person Mathieu    schedule 27.07.2014


Ответы (1)


вам нужно использовать двойники в вашем тесте.

describe UserController do
  it 'sets the request location with Geocoder' do
    geocoder = class_double("Geocoder") # class double
    location = double('location', country: 'some country') # basic double with return values
    expect(geocoder).to receive(:search).and_return(location) # stubbing return value

    post :create, user_params

    user = assigns(:user)
    expect(user.user_country).to eq('some country')
  end
end

таким образом мы создаем фальшивое местоположение и геокодер, а также фальшивые возвращаемые значения. затем мы утверждаем, что возвращаемое значение от геокодера сохраняется как пользовательский атрибут. таким образом, нам на самом деле не нужно проверять, работает ли Geocoder, и это значительно упрощает нашу тестовую настройку.

используемые здесь понятия:

https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/basics/test-doubles https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/verifying-doubles/using-a-class-double https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/configuring-responses/returning-a-value

если вы хотите быть более надежным, вы можете подделать IP-адрес в контексте тестового запроса, а затем указать, какие аргументы получает поддельный геокодер с сопоставлением аргументов: https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/setting-constraints/matching-arguments

в общем, вы должны использовать макеты, чтобы изолировать проблемы ваших тестов. см. https://relishapp.com/rspec/rspec-mocks/v/3-0/docs для получения дополнительной документации

person rickypai    schedule 27.07.2014
comment
спасибо, но когда я делаю это в rspec/controllers Userscontroller, как было предложено, я получаю эту ошибку: Ошибка/ошибка: сообщение: создать, user_params NameError: неопределенная локальная переменная или метод `user_params' для #‹RSpec::ExampleGroups::UsersController:0x0000000990b1f0 ›. Знаете ли вы, почему? Кстати, я использую Devise для создания пользователя с подтверждением электронной почты/пароля/пароля (так что у меня есть контроллеры/RegistrationsControllers и все такое...) - person Mathieu; 28.07.2014
comment
мой код не полный. вам нужно заполнить user_params любым параметром, который вам нужен для создания пользователя. Я полагаю, что это как минимум имя пользователя/электронная почта и пароль - person rickypai; 30.07.2014
comment
хзаха ок, извините за вопрос новичка :). я использую фабричную девушку, поэтому я создам пользователя с ней - person Mathieu; 30.07.2014