1. ホーム
  2. static

PowerMockでvoidを返すスタティックメソッドをモックするには?

2023-07-11 01:24:48

質問

私のプロジェクトにはいくつかの静的なutilメソッドがあり、そのうちのいくつかは単に例外を渡したり投げたりしています。void 以外の戻り値の型を持つ静的メソッドをモックする方法については、多くの例があります。しかし、voidを返す静的メソッドを単に"にモックするにはどうしたらよいでしょうか? doNothing() とすることができますか?

非void版では、以下のようなコード行を使用します。

@PrepareForTest(StaticResource.class)

...

PowerMockito.mockStatic(StaticResource.class);

...

Mockito.when(StaticResource.getResource("string")).thenReturn("string");

しかし StaticResources を返す void を返す場合、コンパイルは次のように文句を言うでしょう。 when(T) はvoidには適用できない...

何かいい案はありませんか?

回避策としては、おそらくすべての静的メソッドが何らかの Boolean を返すようにすればいいのでしょうが、私は回避策が嫌いです。

どのように解決するのですか?

Mockito 3.4.0以降、静的メソッドをモックするための実験的なAPIが導入されました。

以下のサンプルコードは、Mockito 4.3.1でテストされています ( testImplementation("org.mockito:mockito-inline:4.3.1 ) と JUnit Jupiter 5.8.2, OpenJDK 11 でテストしています。

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;

import java.util.UUID;

public class StaticMockTest {

    @Test
    void showCaseStaticMock() {
        try (MockedStatic<StaticMockTest> staticMock = Mockito.mockStatic(StaticMockTest.class)) {
            staticMock.when(StaticMockTest::getUUIDValue).thenReturn("Mockito");
            Assertions.assertEquals("Mockito", StaticMockTest.getUUIDValue());
        }

        // Regular UUID
        UUID.fromString(StaticMockTest.getUUIDValue());
    }

    public static String getUUIDValue() {
        return UUID.randomUUID().toString();
    }
}


前回の回答、おそらくMockito 1.x/2.xとPowermock 1.x/2.xの組み合わせです。

あなたは、実際のインスタンス上でMockitoでそれを行うのと同じ方法でそれを行うことができます。例えば、スタブをチェーンすることができ、以下の行は、最初の呼び出しは何もせず、2回目以降の呼び出しで getResources を呼び出すと例外がスローされます。

// the stub of the static method
doNothing().doThrow(Exception.class).when(StaticResource.class);
StaticResource.getResource("string");
    
// the use of the mocked static code
StaticResource.getResource("string"); // do nothing
StaticResource.getResource("string"); // throw Exception

Matt Lachmanの発言のおかげで、モック作成時にデフォルトの答えを変更しない場合、モックはデフォルトでは何もしないことに注意してください。したがって、以下のコードを書くことは、書かないことと同じです。

doNothing().doThrow(Exception.class).when(StaticResource.class);
    StaticResource.getResource("string");

とはいえ、このテストを読む同僚にとっては、この特定のコードには何も期待していないということが興味深いことでしょう。もちろん、これはどのように受け取られるかに応じて適応させることができます。 理解しやすさ を認識する方法に応じて適応させることができます。


ところで、私の意見では、新しいコードを作成する場合、静的なコードのモックは避けるべきだと思います。Mockitoでは、静的なモックは悪い設計へのヒントであり、保守性の低いコードにつながると考えています。既存のレガシーコードはまた別の話ですが。

一般的に、プライベート・メソッドやスタティック・メソッドをモックする必要がある場合、このメソッドの役割は大きすぎるため、オブジェクトを外部化し、テストされるオブジェクトに注入する必要があります。

お役に立てれば幸いです。

ご挨拶