23

ライブラリ クラスに拡張する子クラスを作成して、既存のライブラリを拡張しています。

子クラスでは、メソッドのほとんどの機能をテストできましinitializeたが、モックsuper呼び出しはできませんでした。子クラスは以下のような感じです。

class Child < SomeLibrary
    def initialize(arg)
        validate_arg(arg)
        do_something
        super(arg)
    end

    def validate_arg(arg)
        # do the validation
    end

    def do_something
        @setup = true
    end
end

呼び出しをモックできるように、rspec テスト (mocha を使用) を作成するにはどうすればよいsuperですか? クラスのinitializeメソッドの機能をテストしていることに注意してください。追加の引数が指定されたときにChild呼び出されない別のコード パスを作成する必要がありますか?super

4

4 に答える 4

2

@myron が示唆したように、おそらく で起こっている動作をテストしたいと思うでしょうsuper

しかし、本当にこれを行いたい場合は、次のようにすることができます。

expect_any_instance_of(A).to receive(:instance_method).and_call_original

仮定

class B < A
  def instance_method
    super
  end
end

class A
  def instance_method
    #
  end
end

免責事項expect_any_instance_ofは弱いテストのマークです (を参照):

この機能は、レガシー コードで作業する場合に便利な場合がありますが、一般的には、いくつかの理由から使用をお勧めしません。

rspec-mocks API は個々のオブジェクト インスタンス用に設計されていますが、この機能はオブジェクトのクラス全体で動作します。その結果、意味的に紛らわしいエッジケースがいくつかあります。たとえば、expect_any_instance_of(Widget).to receive(:name).twice では、特定のインスタンスが name を 2 回受け取ることが期待されるのか、それとも合計で 2 回受け取ることが期待されるのかは明らかではありません。(前者です。)

この機能を使用すると、デザインの匂いがすることがよくあります。テストがやりすぎているか、テスト対象のオブジェクトが複雑すぎる可能性があります。

これは rspec-mocks の最も複雑な機能であり、歴史的に最も多くのバグ報告を受けてきました。(コアチームの誰も積極的に使用していないため、役に立ちません。)

于 2020-12-11T09:47:56.447 に答える
1

このパーティーには少し遅れていますが、superキーワードの使用を控えて代わりに行うこともできます。

class Parent
  def m(*args)
  end
end

class Child < Parent
  alias super_m m

  def m(*args)
    super_m(*args)
  end
end

そうすれば、スーパー メソッドは他のメソッドと同じようにアクセスでき、たとえば、他のメソッドと同じようにスタブ化できます。主な欠点は、スーパー メソッドの呼び出しに引数を明示的に渡す必要があることです。

于 2019-10-15T14:04:53.873 に答える