Java Unit Test - Mockito mock靜態方法


一、當需要mock靜態方法的時候,必須加注解@PrepareForTest和@RunWith。注解@PrepareForTest里寫的類是靜態方法所在的類。

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

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.eq;

@RunWith(PowerMockRunner.class)
@PrepareForTest(String.class)
public class MockPrepareForTest {

    @Test
    public void testStaticMathod () {
        TestString testString = new TestString();

        PowerMockito.mockStatic(String.class);
        PowerMockito.when(String.valueOf(eq(100l))).thenReturn("TEST");

        String result = testString.getTestString(100l);

        assertEquals("TEST", result);
    }

    class TestString {

        public String getTestString(long number) {
            return String.valueOf(number);

        }
    }
}

    以上模擬靜態方法的方式僅適用於JDK8 以下的版本,如果你想在JDK8+的版本模擬靜態方法,可以用以下的方式。

 

 

二、使用最新版本的 Mockito 模擬靜態方,我們測試的重點將是一個簡單的靜態實用程序類:

public class StaticUtils {

    private StaticUtils() {}

    public static List<Integer> range(int start, int end) {
        return IntStream.range(start, end)
          .boxed()
          .collect(Collectors.toList());
    }

    public static String name() {
        return "Baeldung";
    }
}

 

  1. 添加依賴
    讓我們開始將mockito-inline依賴項添加到我們的pom.xml
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>3.8.0</version>
        <scope>test</scope>
    </dependency>

     

  2. 模擬無參靜態方法
    @Test
    void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
        assertThat(StaticUtils.name()).isEqualTo("Baeldung");
    
        try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
            utilities.when(StaticUtils::name).thenReturn("Eugen");
            assertThat(StaticUtils.name()).isEqualTo("Eugen");
        }
    
        assertThat(StaticUtils.name()).isEqualTo("Baeldung");
    }

    如前所述,從 Mockito 3.4.0 開始,我們可以使用Mockito.mockStatic( Class<T> classToMock )方法來模擬對靜態方法調用的調用。此方法為我們的類型返回一個MockedStatic對象,它是一個作用域模擬對象。

    因此,在我們上面的單元測試中,utilities變量表示具有線程局部顯式作用域的模擬。需要注意的是,作用域模擬必須由激活模擬的實體關閉。這就是為什么我們在try-with-resources構造中定義我們的模擬,以便當我們完成我們的作用域塊時模擬會自動關閉。

    這是一個特別好的功能,因為它確保我們的靜態模擬保持臨時。正如我們所知,如果我們在測試運行期間使用靜態方法調用,由於運行測試的並發和順序特性,這可能會對我們的測試結果產生不利影響。

    最重要的是,另一個很好的副作用是我們的測試仍然會運行得非常快,因為 Mockito 不需要為每個測試替換類加載器。

  3. 用參數模擬靜態方法

    現在讓我們看看另一個常見的用例,當我們需要模擬一個有參數的方法時:

    @Test
    void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
        assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
    
        try (MockedStatic<StaticUtils> utilities = Mockito.mockStatic(StaticUtils.class)) {
            utilities.when(() -> StaticUtils.range(2, 6))
              .thenReturn(Arrays.asList(10, 11, 12));
    
            assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
        }
    
        assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
    }

    在這里,我們遵循相同的方法,但這次我們在我們的when子句中使用lambda 表達式,我們在其中指定方法以及我們想要模擬的任何參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM