2017-03-04 20 views
1

Minitestを使用して間違ったクラスへのメソッドディスパッチに関して非常に奇妙な問題が発生しています。Rubyメソッド呼び出しが間違った(トップレベルモジュール)クラスになる

私はdnsrubyライブラリ(https://github.com/alexdalitz/dnsruby)のメンテナンスを手伝っており、断続的に失敗する特定のテストがあります(https://github.com/alexdalitz/dnsruby/blob/master/test/tc_resolv.rb#L56)。

てこにブレークポイントを設定することで、私はそれが失敗したとき、それは内部ルビー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には、Resolvクラスを指定しないでください。

これをどのように修正できますか?

+0

誰かがresolvを必要としていることが分かったら、そこで起こっていることを見つけやすくなります。 resolv.rbでエラーを発生させようとしましたが、どこに必要なのか分かりましたか? – phoet

+0

興味深いアイデア。私はそれを行い、それを必要としていたテストファイルを見つけました。しかし、そのファイルと問題のテストファイルだけをテストしたとき、エラーは発生しませんでした。 :: ResolvとDnsruby :: Resolvの両方が利用可能でしたが、正しい(つまり異なる)クラスを指していて、テストは合格しました。したがって、問題は 'resolv'が必要であるということではなく、何とかDnsruby :: Resolvが_some_の場合にはResolvを指すように上書きされているということです。 –

+0

'TracePoint'または' set_trace_func'を使って、あるクラスによってオーバーライドされるかどうかを調べることができます。 – phoet

答えて

0

トップレベルのinclude Dnsrubyを削除して問題を解決しました。 (これをスポッティングのためのRubyコミュニティのメンバーhttps://github.com/matt-gloverに感謝!)

詳しい詳細はhttps://github.com/alexdalitz/dnsruby/issues/112でGithubの問題であり、かつ修正はhttps://github.com/alexdalitz/dnsruby/pull/121/filesでプル要求です。

私を混乱させるもの...トップレベルにDnsruby :: Resolvクラスが含まれていることが予想されますが、逆のことが起こったようです。

関連する問題