【问题标题】:Rspec: unit testing for the merge! method in Ruby hashRspec:合并的单元测试! Ruby哈希中的方法
【发布时间】:2018-12-18 21:32:56
【问题描述】:

我有一段代码:

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。有什么建议吗?

【问题讨论】:

  • 为什么要为另一个(内置)类的方法编写测试?从风格的角度来看,avoid using {} for multi-line blocks。试图破译你的例子让我头疼。
  • 运行单元测试时出现以下错误。 NoMethodError: undefined method '[]' for nil:NilClass
  • 你的例子太复杂了。先简化一下。您正在进行十个方法调用,链接多个方法调用,包括条件调用,并将救援全部包含在一行中。您显示的错误根本无助于破译它,因为您没有包含测试代码,最重要的是,您在那次调用 [] 四次线。让您的生活更轻松:将此代码重构为可读且合理的代码,然后对其进行测试。
  • 我正在修改我的代码(提供一个更简单的示例)。
  • @anothermh 我刚刚添加了一段不同的代码

标签: ruby unit-testing rspec


【解决方案1】:

假设在您给出的示例中 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 具有您首先期望的哈希键和值。

更新

在下面的 cmets 中,您询问了如何验证它是否具有您需要的密钥。这个问题的答案取决于一些事情,例如在没有它的情况下您希望看到的行为以及您使用的 Ruby 版本。

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

这是使用 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

如果rqst 没有键author 并带有一个名为username 的子键和另一个名为name 的子键,我们正在做的是调用next。这是可行的,因为如果哈希中没有这些键,dig 将返回 nil。

让我们假装一下rqst == {}。该行的解释方式是:

next unless nil && nil

由于在 Ruby 中 nil 是 falsy,它最终会调用 next 以跳过当前的 rqst 值并继续迭代中的下一个值。

我还删除了selected_unit_req,因为它不必要地重复;因为您已经确切地知道您想要从rqst 中获得哪些键/值,所以无需仅使用这些值创建新哈希;相反,您可以提取这些值并在需要时直接使用它们。

【讨论】:

  • 感谢您的回复,但我如何确保这一点?我对 ruby​​ 很陌生,所以很难弄清楚这一点
  • @shitgetsreal 我已经更新了我的答案来解释这样做的方法。
猜你喜欢
  • 2016-11-27
  • 2013-08-22
  • 2011-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 2019-02-21
相关资源
最近更新 更多