Rspec:用于合并的单元测试! Ruby哈希中的方法

时间:2018-12-18 21:32:56

标签: ruby unit-testing rspec

我有一段代码,其中有:

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 :(得分:0)

让我们假设在您给的示例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版本。

如果没有键,并且您使用的是现代版本的Ruby(> = 2.3.0),我将假设可以跳过rqst

这是对Hash类使用dig方法的一种方法:

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且另一个子键为{{ 1}}。之所以有效,是因为如果哈希中没有这些键,username将返回name

让我们假装dig。该行的解释方式是:

nil

由于rqst == {}在Ruby中是falsy,因此最终会调用next unless nil && nil 跳过当前的nil值,然后继续进行迭代中的下一个值。 / p>

我也删除了next,因为它不必要地重复了;由于您已经确切知道要从rqst中获得什么键/值,因此无需仅使用这些值创建新的哈希;相反,您可以提取这些值并在需要的地方直接使用它们。