3

私は転送メソッドを持つクラスを持っていますfoo

void foo( Concrete c, String s ) { c.bar( s ); }

foo実際に前進するかどうかをテストしたいと思います。私にとって残念なことに、Concreteこれはサードパーティライブラリのクラスであり、インターフェイスではなく具象型です。したがってClassImposteriser、モックを作成するにはJMockで使用する必要Concreteがあるため、テストケースでは次のようにします。

@Test
public final void testFoo() {
   Mockery context = new JUnit4Mockery() {{
      setImposteriser(ClassImposteriser.INSTANCE);
   }};

  final Concrete c = context.mock(Concrete.class);
  final String s = "xxx" ;

  // expectations
  context.checking(new Expectations() {{

     oneOf (c).bar(s); // exception gets thrown from here
  }});


  new ClassUnderTest.foo( c, s );
  context.assertIsSatisfied();

}

残念ながら、Concrete.bar順番にスローするメソッドを呼び出します。そのメソッドは最終的なものなので、オーバーライドすることはできません。さらに、その行をコメントアウトしても、が呼び出されnew ClassUnderTest.foo( c, s );たときではなく、JMockが例外を設定したときに例外がスローさfooれます。

ClassUnderTest.fooでは、そのメソッドがどのように転送されるかをテストするにはどうすればよいConcrete.barですか?

編集:
はい、バーは最終です。

私の解決策は一般的なものではありませんが、サードパーティライブラリの「Tester」クラスを使用して正しく設定することでしたConcrete

4

4 に答える 4

5

Concrete.bar() が final なのか、Concrete.somethingElse() が final で Concrete.bar() から呼び出されたのかは、質問のテキストからは明らかではありません。

Concrete.bar()が finalでない場合、次のように Concrete の手書きスタブを作成します。

public class ConcreteStub extends Concrete
{
    public int numCallsToBar = 0;
    @Override
    public void bar(String s) { numCallsToBar++; }
}

そしてあなたのテストコードで:

ConcreteStub c = new ConcreteStub();
foo(c,"abc");
assertEquals(1,c.numCallsToBar);

Concrete.bar()が finalの場合、より複雑になり、答えは Concrete の複雑さとプロジェクトでの Concrete クラスの使用によって異なります。Concrete の使用が十分に単純な場合は、Concrete をインターフェイス ( Adapter Pattern ) にラップして、簡単にモックできるようにすることを検討します。

アダプター パターン ソリューションの利点: プロジェクトで Concrete を使用した後にインターフェイスに名前を付けることで、動作を明確にすることができます。テストしやすくなります。

アダプター パターン ソリューションの欠点: より多くのクラスが導入されますが、運用コードにはほとんどメリットがありません。Concrete が何をするのかわかりませんし、インターフェイスで Concrete をラップするのは実際的ではないかもしれません。

于 2009-04-12T06:37:40.987 に答える
4

クラスのモック化と最終的な制限を回避する方法については、http: //www.jmock.org/mocking-classes.htmlを参照してください。

于 2009-05-22T20:02:07.620 に答える
0

メソッドが最終的なものである場合、それについて多くを行うことはできません。これがサードパーティのライブラリである場合は、ベニヤレイヤーでラップしてモック、統合テストを実行してライブラリに対してテストすることを検討します。ロックダウンされたコードを模倣するフレームワークは他にもありますが、それは素晴らしいアイデアではないと思われるため、サポートしていません。

于 2009-05-21T12:15:20.203 に答える
0

JMockitなどのより機能的なモック ツールを使用します。テストは次のように記述できます。

@Test
public void testFoo(final Concrete c)
{
  final String s = "xxx";

  new Expectations() {{
    c.bar(s);
  }};

  new ClassUnderTest().foo(c, s);
}

JMockit の場合Concrete、インターフェイス、最終クラス、抽象クラスなどのいずれであっても違いはありません。@RunWithまた、 を使用したり、基本テスト クラスを拡張したり、 のようなメソッドを呼び出したりする必要はありませんassertIsSatisfied()。すべてが透過的な方法で自動的に行われます。

于 2009-12-31T14:39:56.473 に答える