4

私が持っているクラスの単体テストを書きたいです。このクラスにはパブリック メソッドがあり、パブリック メソッド内には、同じクラスのプライベート メソッドへの呼び出しがあります。これらのプライベート メソッドの呼び出しをモックしたいと考えています。クラスは次のようになります。

public class SomeClass {
    public int somePublicMethod(int num) {
        int num2 = somePrivateMethod1(num);
        int num3 = somePrivateMethod2(num);

        return num2 + num3;
    }

    private int somePrivateMethod1(int num) {
        return 2*num;
    }

    private int somePrivateMethod2(int num) {
        return 3*num;
    }
}

私の単体テストでは、Mockito と TestNG で PowerMock を使用しようとしています。somePublicMethod をテストするテストでの私の試みは次のとおりです。

import static org.powermock.api.mockito.PowerMockito.doReturn;
import static org.powermock.api.mockito.PowerMockito.spy;

import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.Assert;
import org.testng.annotations.Test;

@PrepareForTest(SomeClass.class)
public class SomeClassTest {

    @Test
    public void testSomePublicMethod() throws Exception {
        int num = 4;        

        SomeClass someClassSpy = spy(new SomeClass());

        doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
        doReturn(12).when(someClassSpy, "somePrivateMethod2", num);

        int result = someClassSpy.somePublicMethod(num);

        Assert.assertEquals(result, 20);
    }
}

このテストを実行すると、例外といくつかのヒントが表示されます。

FAILED: testSomePublicMethod
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:31)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!

オンラインでいくつかの例を見てきましたが、PowerMock と Mockito および TestNG を使用して、特に私がやりたいことを行う例は見つかりませんでした。私が別の方法でできることについて、誰かが私にいくつかの指針を与えることができますか?

4

3 に答える 3

5

これはPowerMockの問題ではないと思います。そのままでも問題なく動作するようです。TestNGとPowerMockの相互作用に問題があるのだろうか?

TestNGの経験がないので、JUnitでクラスを実行してみました。 SomeClassそのままにして、SomeClassTestJUnitを使用するように最小限の変更を加えました。

import static org.powermock.api.mockito.PowerMockito.*;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeClass.class)
public class SomeClassTest {

    @Test
    public void testSomePublicMethod() throws Exception {
        final int num = 4;

        final SomeClass someClassSpy = spy(new SomeClass());

        doReturn(8).when(someClassSpy, "somePrivateMethod1", num);
        doReturn(12).when(someClassSpy, "somePrivateMethod2", num);

        final int result = someClassSpy.somePublicMethod(num);

        Assert.assertEquals(result, 20);
    }
}

テストに合格します。

PowerMockRunner.classJUnitの場合と同様に、 using@RunWIthまたは同様のアノテーションを指定する必要がありますか?その注釈を削除すると、あなたが投稿したのと同じエラーメッセージが表示されます。

編集:

このリンクによると: http ://code.google.com/p/powermock/wiki/TestNG_usage

PowerMockオブジェクトファクトリを使用するようにTestNGに指示する必要があります。これをプログラムで行うには、次のようなメソッドをテストクラスに追加します。

@ObjectFactory
public IObjectFactory getObjectFactory() {
    return new org.powermock.modules.testng.PowerMockObjectFactory();
}

または、安全のために、PowerMockTestCaseから拡張することもできます。

@PrepareForTest(SomeClass.class)
public class SomeClassTest extends PowerMockTestCase {
   //...
}
于 2012-05-11T12:34:58.660 に答える
1

その方法ではできません。リフレクションを使用しようとしましたか?

リフレクションを使用すると、invoke メソッドをモックすることでプライベート メソッドをモックできます。または、より簡単に、パブリック テンポラリーに変更してから、テスト後 (おそらく、tearDown で)、プライベートに戻すことができます。

この助けを願っています。

于 2012-05-10T09:38:16.457 に答える
0

ここでMockitoの制限に達していると思います。同様のケースで、Powermock メソッドの置換を使用するか、ターゲット メソッドを保護されているとして宣言し、テスト対象のクラス インスタンスを構築するときにそれをオーバーライドします。それが役立つことを願っています。

于 2012-05-10T09:33:28.090 に答える