- 開発
rspecで継承したクラスにany_instance.stubを使うとSystemStackError (stack level too deep) になる
タイトルのままですが、rspecで
User.any_instance.stub(:enabled?) { true }
のような処理をする際、SystemStackError stack level too deepが発生することがあります。
これは、継承の親クラスに対してany_instance指定し、実際には子クラスのメソッドが呼び出された場合に発生します。
仕様のようです。
https://github.com/rspec/rspec-mocks/issues/94
この辺りで無限ループしていますね。
# gems/rspec-mocks-2.10.1/lib/rspec/mocks/any_instance/recorder.rb:173 def observe!(method_name) stop_observing!(method_name) if already_observing?(method_name) @observed_methods << method_name backup_method!(method_name) @klass.class_eval(<<-EOM, __FILE__, __LINE__) def #{method_name}(*args, &blk) self.class.__recorder.playback!(self, :#{method_name}) # ここ self.__send__(:#{method_name}, *args, &blk) end EOM end
特に、単一テーブル継承(UserのサブクラスMemberとAdminを作るなど)を使った場合に、うっかりやりがちです。
解決策としては、子クラス(MemberやAdmin)に直接any_instance指定すればOKです。