4

DerivedMockito を使用して TDD で新しいクラス ( ) を作成していますが、次のような場合があります。

クラスベース:

public abstract class Base<T>{
    //.......
    protected final T baseCreate(T entity){
        // implementation
    }
}

Class Derived (これは私が TDD を使って書いているクラスです):

public class Derived extends Base<MyObject> {
    //.......
    public MyObject create(MyObject entity){
        baseCreate(entity);    //This is what I want the implementation to be
    }
}

私がテストを書くようになったとき、私はbaseCreateメソッドを呼び出すことを余儀なくされました - 私はそれを行う方法を理解できませんでした. メソッドがクラス内のcreate(...)メソッドをDerived呼び出すことを確認するために、mockito を使用する方法はありますか?baseCreate(...)Base

ありがとう。

4

3 に答える 3

5

単体テストは、クラスの実装ではなく、クラスの動作をテストすることです。したがって、 が明示的に呼び出されているかどうかを気にする必要はありません。むしろ、 が外部オブザーバーの観点から期待するとおりにBase呼び出すbaseCreate()かどうかに注意してください。Derivedcerate()

于 2012-05-17T15:14:41.843 に答える
4

Attila は、ほとんどの場合に適しています。あなたがテストしたいのは、 create がどのように行うかではなく、実際に行うべきだと思うことを行うことです。ここにあるケースは、「baseCreate が自分のやりたいことを実行することは既にわかっているので、それを再テストしたくはありません。単に呼び出されることだけです。」のように聞こえます。これは事実かもしれませんが、もしそうなら、あなたのスーパークラスは本当に協力者です. これは、継承よりも委譲を優先する理由の一部です。とはいえ、設計上の決定に戻って変更するのが難しい場合もあるため、既存のものをテストする必要があります。

「作成」が全体としてやりたいことを実行することを確認することを引き続き優先する必要がありますが、baseCreate が実際に多くのことを実行していて、コラボレーターなどの多くの設定が必要な場合があるかもしれません。テストが困難で脆い。その場合、「スパイ」を使用する必要があります。スパイは「実際の」オブジェクトをラップし、特に別の期待を作成しない限り、実際のメソッド呼び出しに委任します。

baseCreate を公開できる場合は、次のように Mockito を使用できます。

@RunWith(MockitoJUnitRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
public class YourTestCase {
    @Spy
    private Derived classUnderTest = new Derived();

    @Test
    public void privatePartialMockingWithPowerMock() {        
        MyObject myObject = new MyObject();
        when(classUnderTest.baseCreate(myObject)).thenReturn(myObject);

        // execute your test
        classUnderTest.create(myObject);

        verify(classUnderTest).baseCreate(myObject);
    }
}

baseCreate を公開できない場合は、 PowerMockを使用できると思います。プライベート メソッドを検証できますが、保護されたメソッドも実行できない理由はないと思います。

@RunWith(PowerMockRunner.class)
// We prepare PartialMockClass for test because it's final or we need to mock private or static methods
@PrepareForTest(Derived.class)
public class YourTestCase {
    @Test
    public void testCreate() {        
        Derived classUnderTest = PowerMockito.spy(new Derived());
        MyObject myObject = new MyObject();

        // use PowerMockito to set up your expectation
        PowerMockito.doReturn(myObject).when(classUnderTest, "baseCreate", myObject);

        // execute your test
        classUnderTest.create(myObject);

        // Use PowerMockito.verify() to verify result
        PowerMockito.verifyPrivate(classUnderTest).invoke("baseCreate", myObject);
    }
}
于 2012-05-17T18:07:06.657 に答える
1

あなたは TDD を使用していると言います - おそらく、どちらDerivedBaseまたは両方の必要な動作の仕様がいくつかあります。そのため、その仕様に関するいくつかのテストを作成します。Derivedこれらのテストでは、拡張する必要はありませんBase。各クラスの特定の動作が必要になるだけです。継承を一切使わずに実装できる動作になります。

テストに合格すると、TDD の次の段階が開始されます。これは「リファクタリング」段階であり、クラスの設計方法の改善を探します。Derivedこれは、 extendBaseを作成し、createメソッド callを作成することを決定するポイントですbaseCreate。素晴らしいことは、リファクタリングを行うときに、正しく機能することを確認するためのいくつかのテストが既に行われていることです。

于 2012-05-18T08:34:43.427 に答える