Rspec: модульное тестирование на слияние!метод в хэше Ruby - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть код, который имеет:

requests.each do |request|
  request.each do |rqst|
    select_keys = ["author", "author_name"]
    selected_unit_req = rqst.select { |m| select_keys.include?(m) }
    user = Etl::Models::User.where(username: selected_unit_req["author"]["username"] )
    user.merge!({ author_name: selected_unit_req["author"]["name"] })
  end
end

Я не могу проверить слияние!метод, получая NoMethodError:undefined method '[]' for nil:NilClass, когда я запускаю свои существующие модульные тесты.Есть предложения?

1 Ответ

0 голосов
/ 19 декабря 2018

Предположим, что в приведенном вами примере rqst возвращает пустой хеш {}.

Когда вы устанавливаете selected_unit_req, для него устанавливается пустой хеш:

selected_unit_req = rqst.select { |m| select_keys.include?(m) }
=> {}

При последующем вызове selected_unit_req["author"] проверяется хеш для ключа с именем author, и это возвращает nil:

selected_unit_req["author"]
=> nil

Таким образом, выполнение полного вызова selected_unit_req["author"]["username"] можно увидеть какэквивалентно следующему:

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

Вот почему возникает ошибка;вы ожидаете, что selected_unit_req["author"] вернет хеш с ключом username, но вместо этого он возвращает nil.

Убедитесь, что selected_unit_req имеет ключи и значения хеша, которые вы ожидаете первыми.

Обновление

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

Я собираюсь предположить, что этоможно пропустить rqst, если у него нет ключей и вы используете современную версию Ruby (> = 2.3.0).

Вот один из способов сделать это с помощью dig метод для класса Hash:

request.each do |rqst|
  next unless rqst.dig('author', 'username') && rqst.dig('author', 'name')
  user = Etl::Models::User.where(username: rqst['author']['username'] )
  user.merge!({ author_name: rqst['author']['name'] })
end

То, что мы делаем, вызывает next, если rqst не имеет ключа author с подключом с именем username и другой подраздел с именем name.Это работает, потому что dig вернет nil, если в хэше нет этих ключей.

Давайте на мгновение представим, что rqst == {}.Как будет интерпретироваться эта строка:

next unless nil && nil

Так как nil это ложь в Ruby, в итоге он вызывает next, чтобы пропустить текущее значение rqst и переместитьсяк следующему в итерации.

Я также удалил selected_unit_req, потому что это излишне повторяется;поскольку вы уже точно знаете, какие ключи / значения вы хотите получить из rqst, нет необходимости создавать новый хэш только с этими значениями;вместо этого вы можете просто извлечь эти значения и использовать их непосредственно там, где это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...