簡體   English   中英

如何在沒有powermock的情況下模擬靜態方法

[英]How to mock static method without powermock

在 JUnit 中進行測試時,有什么方法可以模擬靜態 util 方法?

我知道 Powermock 可以模擬靜態調用,但我不想使用 Powermock。

有沒有其他選擇?

(不過我假設你可以使用 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();
    }
}

這是我寫的一篇關於間諜的文章,其中包括類似的案例,如果您需要更多的洞察力: sourceartists.com/mockito-spying

當你的靜態代碼給你的單元測試帶來麻煩時; 所以你覺得你必須“嘲笑它”,你有這些選擇:

  • 你轉向 PowerMock(ito)。 工作正常。
  • 你轉向 JMockit。 工作正常,也是。
  • 如果您正在測試自己編寫的代碼,您可能想退后一步問問自己:“為什么我編寫的代碼現在很難進行單元測試?”

換句話說:如果您想使用模擬框架,則必須使用上面列出的框架之一。 一方面,這絕對是公平的。 靜態是 Java 語言的一部分; 那么為什么不使用允許您處理它的框架呢?

但是當然:那時您的生產代碼中仍然有靜態調用。 導致緊耦合,防止多態

所以:如果你能擺脫靜態調用(即使只是使用另一個答案中建議的解決方法) - 那就更好了。 如果不是:Mockito 無能為力; 你需要字節碼操作的魔力。 JVM 代理。

您可以使用Mockito (自3.4.0版起)來模擬靜態方法。

給定一個類Foo

class Foo{
  static String method() {
    return "foo";
  }
}

這是測試:

@Test
void testMethod() {
    assertEquals("foo", Foo.method());
    try (MockedStatic mocked = Mockito.mockStatic(Foo.class)) {
        mocked.when(Foo::method).thenReturn("bar");
        assertEquals("bar", Foo.method());
        mocked.verify(Foo::method);
    }
    assertEquals("foo", Foo.method());
}

這需要依賴org.mockito:mockito-inline:3.4.0或更新版本。

我很幸運地做了一些類似於 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();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM