【问题标题】:Ruby Method Call Made to Wrong (Top Level Module) ClassRuby 方法调用错误(顶级模块)类
【发布时间】:2017-07-24 15:51:24
【问题描述】:

关于使用 Minitest 将方法分派到错误的类,我遇到了一个非常奇怪的问题。

我正在帮助维护 dnsruby 库 (https://github.com/alexdalitz/dnsruby),我们有一个间歇性失败的特定测试 (https://github.com/alexdalitz/dnsruby/blob/master/test/tc_resolv.rb#L56)。

通过在 pry 中设置断点,我发现当它失败时,它使用的是内部 Ruby Resolv 类的 getname 方法,而不是代码中指定的 Dnsruby::Resolv 类。 ::ResolvDnsruby::Resolv 似乎都指向 Ruby 内部的 Resolv 类:

[1] pry(#<TestResolv>)> ::Resolv.object_id => 70320518250220 [2] pry(#<TestResolv>)> Dnsruby::Resolv.object_id => 70320518250220

单独运行测试时不会发生错误 (ruby test/tc_resolv.rb)。当与其他测试结合使用时(使用ruby test/ts_online.rb 并修改其正在运行的测试文件列表),它通常会失败但有时不会。我发现似乎与失败相关的唯一因素是运行的测试代码量;运行的测试越多,失败的可能性就越大。

当测试成功时,::Resolv 甚至没有被定义:

[1] pry(#<TestResolv>)> ::Resolv.object_id NameError: uninitialized constant Resolv

我在我们的代码库中搜索了require 'resolv',但没有找到。也许我们正在使用的另一个库需要它。尽管如此,Dnsruby::Resolv 中的Dnsruby:: 不应该指定我们自定义的Resolv 类吗?

我们如何解决这个问题?

【问题讨论】:

  • 我想一旦你发现谁需要解决,就更容易发现那里发生了什么。您是否尝试过在 resolv.rb 中提出错误以便查看需要的位置?
  • 有趣的想法。我这样做并找到了一个需要它的测试文件。但是,当我只测试那个文件和有问题的测试文件时,并没有发生错误; ::Resolv 和 Dnsruby::Resolv 都可用,但指向正确的(即不同的)类,并且测试通过了。所以问题不在于需要'resolv',而是在某些情况下,Dnsruby::Resolv 被覆盖以指向 ::Resolv。
  • 您可以使用TracePointset_trace_func 来检查它是否被某个类覆盖。
  • 我只是简单地查看了 github 问题。会不会,问题实际上与赛璐珞有关?两个并发实例,或者没有正确关闭或类似的东西?测试套件中有两个 Celluloid.boot 但没有 Celluloid.shutdown 调用。
  • @phoet 感谢您的建议。我在 github.com/alexdalitz/dnsruby/issues/122 上打开了一个关于您发现的赛璐珞问题的新 Github 问题。

标签: ruby module minitest


【解决方案1】:

问题已通过删除顶层中不应该存在的include Dnsruby 得到解决。 (感谢 Ruby 社区成员 https://github.com/matt-glover 发现这一点!)

更多细节在https://github.com/alexdalitz/dnsruby/issues/112 的 Github 问题中,修复在https://github.com/alexdalitz/dnsruby/pull/121/files 的拉取请求中。

让我感到困惑的一件事...我原以为 include 会导致 Dnsruby::Resolv 类被拉到顶层,但似乎情况正好相反。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多