web-dev-qa-db-ja.com

パワーモックなしで静的メソッドをモックする方法

JUnitでテスト中に静的utilメソッドをモックできる方法はありますか?

Powermockは静的呼び出しをモックできることは知っていますが、Powermockは使いたくありません。

代替手段はありますか?

18
gati sahu

(ただし、Mockitoを使用できると思います)私の頭に浮かぶものは何もありませんが、そのような状況になると、次の戦略を使用する傾向があります。

1)テスト対象のクラスで、静的な直接呼び出しを、静的な呼び出し自体をラップするパッケージレベルメソッドへの呼び出しに置き換えます。

public class ToBeTested{

    public void myMethodToTest(){
         ...
         String s = makeStaticWrappedCall();
         ...
    }

    String makeStaticWrappedCall(){
        return Util.staticMethodCall();
    }
}

2)テスト中にクラスをスパイし、ラップされたパッケージレベルメソッドをモックします。

public class ToBeTestedTest{

    @Spy
    ToBeTested tbTestedSpy = new ToBeTested();

    @Before
    public void init(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void myMethodToTestTest() throws Exception{
       // Arrange
       doReturn("Expected String").when(tbTestedSpy).makeStaticWrappedCall();

       // Act
       tbTestedSpy.myMethodToTest();
    }
}
12
Maciej Kowalski

staticがある場合、ユニットテストで問題が発生します。 「あざける」必要があると感じるように、次のオプションがあります。

  • PowerMock(ito)を使用します。正常に動作します。
  • JMockitを使用します。うまく動作します。
  • yourselfで記述したコードをテストしている場合は、一歩下がって、「なぜ今は単体テストが難しいと思うコードを書いたのですか?」

つまり、モックフレームワークを使用する場合は、上記のいずれかを使用する必要があります。一方では、それは絶対に公平です。 staticは、Java言語の一部です。したがって、それを処理できるフレームワークを使用してみませんか?

しかし、もちろん、あなたはまだ実動コードでstatic呼び出しを持っています。密結合につながり、多型を防ぎます。

そのため、static呼び出しを削除できる場合(他の回答で提案されている回避策を使用する場合でも)-さらに良いことです。そうでない場合:Mockitoは役に立ちません。バイトコード操作の魔法が必要です。 JVMエージェント。

4
GhostCat

Maciejが上記の答えで提案したことと似たようなことをすることで、私は多くの幸運を得ました。 Java8では、これらの静的メソッドを機能的なインターフェースでラップして、インジェクトやモックがより簡単になるようにします。例えば:

public class MyClass {
    private MyStaticWrapper staticWrapper;

    public MyClass(final MyStaticWrapper staticWrapper) {
        this.staticWrapper = staticWrapper;
    }

    public void main() {
        ...
        staticWrapper.doSomething();
        ...    
    }
}    

public interface MyStaticWrapper {
    default void doSomething() {
      Util.annoyingUntestableStaticFunction();
    }
}
0
Bryce