6

JUNIT + Mockito を使用して単体テストを作成し、次のようなメソッドをテストしています。

public someObject methodUnderTest(){
  SomeObject obj = SomeAbstractClass.someMethod();

  if(obj!=null){
    obj.someOtherMethod();
  }

  return someThing;
}

そして、上記のコードフラグメントで言及されている呼び出しをモックしたいabstract Class "SomeAbstractClass"ので、次のような「obj」の呼び出しを確認できます。

verify(SomeAbstractClass).someMethod();
verify(obj).someOtherMethod();

次のようなmockito機能を使用してみました:Mockito.CALLS_REAL_METHODS Mockito.RETURNS_MOCKS

ただし、依存関係が SomeAbstractClass で利用できないため、それらは機能しません。

ノート:

1) SomeObject はインターフェイスです。

2) 上記のコード フラグメントをテストする手法が必要です。上記のコード フラグメントを使用するように制限されており、コード フラグメントを変更することはできません。

4

4 に答える 4

2

PowerMockを使用して、静的メソッドと最終メソッドをモックできます。

于 2012-05-26T12:34:25.483 に答える
2

問題は、CALLS_REAL_METHODS の使用がクラス全体に適用され、特定のメソッドを実際にモックしたい (つまり、「部分モック」を作成したい) ことのようです。ここには 2 つのオプションthenCallRealMethodCALLS_REAL_METHODSあります。

public void testMethodUnderTest_mockSpecificThings() {
    SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class);
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
    when(myAbstractClass.someMethod()).thenReturn(foo);
    when(myAbstractClass.methodUnderTest()).thenCallRealMethod();

    myAbstractClass.methodUnderTest();

    verify(myAbstractClass).someMethod();
    verify(myObject).someOtherMethod();
}

public void testMethodUnderTest_makeSpecificRealCalls() {
    SomeAbstractClass myAbstractClass =
        Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS);
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class);
    // overrides the default answer
    when(myAbstractClass.someMethod()).thenReturn(myObject);

    myAbstractClass.methodUnderTest();

    verify(myAbstractClass).someMethod();
    verify(myObject).someOtherMethod();
}

SomeAbstractClass は実際にはインスタンス化されないことに注意してください。そのため、変数の初期化 (フィールドが宣言されているインライン初期化を含む) など、抽象クラス コンストラクターの動作に依存する場合は、それらの呼び出しを自分で明示的に行う必要があります。

于 2012-05-30T19:48:40.923 に答える
1

匿名クラスを使用する:

public interface SomeObject {
     public Object someOtherMethod();
}

public abstract class SomeAbstractClass {
    abstract SomeObject someMethod();
}

@Test
public void test() {
    SomeAbstractClass target = new SomeAbstractClass() {
        SomeObject someMethod() {
            // some impl
            SomeObject someObject = new SomeObject() {
                public Object someOtherMethod() {
                    // some other impl
                }
            };
            return someObject;
        }
    };

    // now test target
}
于 2012-05-26T10:09:04.570 に答える
1

前提: 単体テストを作成する場合、テスト済みのメソッドを少し変更できると思います。

解決:

  1. オーバーライド可能なメソッドへの静的メソッド呼び出しを抽出します。
public someObject methodUnderTest() {
    SomeObject obj = getSomeObject();

    if(obj!=null){
      obj.someOtherMethod();
    }

    return someThing;
}

protected SomeObject getSomeObject() {
    return SomeAbstractClass.someMethod();
}
  1. 次に、Mockito Spy を使用して、実際にテストするオブジェクトを部分的にモックできます。
private ClassUnderTest classUnderTest;

@Before
public void setUp() {
    classUnderTest= new ClassUnderTest();
    classUnderTest = Mockito.spy(classUnderTest);
}

@Test
public void test() {
    SomeObject someObject = Mockito.mock(SomeObject.class);
    when(classUnderTest.getSomeObject()).thenReturn(someObject);
    classUnderTest.methodUnderTest();
    verify(someObject).someOtherMethod();
}

@Test
public void testNull() {
    when(classUnderTest.getSomeObject()).thenReturn(null);
    classUnderTest.methodUnderTest();
    verify(something);
}
于 2012-05-28T11:57:21.973 に答える