2016-05-05 44 views
0

考慮以下字段和來自需要測試的類的方法。如何讓PowerMock從靜態方法返回預期值

private final static String pathToUUID = "path/to/my/file.txt"; 

public String getUuid() throws Exception { 
    return new String(Files.readAllBytes(Paths.get(pathToUUID)));; 
} 

UUID存儲在應用程序第一次運行時創建的文件中。 A file.txt存在於pathToUUID指示的位置。我正在嘗試(並努力)爲這種方法編寫單元測試。

@RunWith(PowerMockRunner.class) 
@PrepareForTest({Files.class}) 
public class MyTest { 

    private final String expected = "19dcd640-0da7-4b1a-9048-1575ee9c5e39"; 

    @Test 
    public void testGetUuid() throws Exception { 
     UUIDGetter getter = new UUIDGetter(); 
     PowerMockito.mockStatic(Files.class); 
     when(Files.readAllBytes(any(Path.class)).thenReturn(expected.getBytes()); 
     String retrieved = getter.getUuid(); 
     Assert.assertEquals(expectedUUID, retrieved); 
    } 
} 

不幸的是when().thenReturn()測試時,不會調用和測試執行的集成測試,從文件讀取系統文件並返回它的價值,而不是簡單地模擬值i期待。但是,如果我在測試方法中欺騙Files.readAllBytes()的電話並將結果回顯到控制檯,則會顯示expected值。

那麼,我怎樣才能讓我的測試方法正確地與PowerMock when()-thenReturn()模式功能?

回答

0

對於任何面臨着類似的問題,我解決了這個通過進行以下修改我的測試類:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({UUIDStasher.class}) 
public class TestUUIDStasher { 

    private final String expectedUUID = "19dcd640-0da7-4b1a-9048-1575ee9c5e39"; 
    Path spoofPath = Paths.get("C:\\TSG"); 

    @Before 
    public void setup() throws Exception { 
     MockitoAnnotations.initMocks(this); 
     PowerMockito.mockStatic(Paths.class); 
     PowerMockito.mockStatic(Files.class); 
     when(Paths.get(any(String.class))).thenReturn(spoofPath); 
     when(Files.readAllBytes(any(Path.class))).thenReturn(expectedUUID.getBytes()); 
    } 

    @Test 
    public void testGetUUID() throws Exception { 
     UUIDStasher stasher = new UUIDStasher(); 
     String retrieved = stasher.getUuid(); 
     Assert.assertEquals(expectedUUID, retrieved); 
    } 
} 
0

你需要測試的課程寫得很糟糕。路徑不應該被硬編碼 - 使其可參數化 - 例如通過構造函數注入路徑。然後,在您的集成測試中,只需將路徑注入您的測試資源,即可開始使用。沒有PowerMock,沒有黑客 - 簡單的構造函數注入。

0

使用PowerMock時,JDK類很難處理。這是我會在你的情況做:

重構UUIDGetter添加用於測試的構造函數接受到的「uuid」文件的路徑:

package so37059406; 

import java.nio.file.Files; 
import java.nio.file.Paths; 

public class UUIDGetter { 

    private final static String PATH_TO_UUID = "path/to/my/file.txt"; 

    private final String path; 

    public UUIDGetter() { 
     this(PATH_TO_UUID); 
    } 

    // for testing purposes 
    protected UUIDGetter(final String path) { 
     this.path = path; 
    } 

    public String getUuid() throws Exception { 
     return new String(Files.readAllBytes(Paths.get(this.path))); 
    } 
} 

然後測試它像這樣:

package so37059406; 

import org.junit.Test; 

import static org.junit.Assert.assertEquals; 

public class UUIDGetterTest { 
    @Test 
    public void testGetUuid() throws Exception { 
     final UUIDGetter getter = new UUIDGetter(getClass().getClassLoader().getResource("so37059406/uuid.txt").getPath()); 
     assertEquals("19dcd640-0da7-4b1a-9048-1575ee9c5e39", getter.getUuid()); 
    } 
} 

使用命名的資源文件(在測試資源文件夾中)「so37059406/uuid.txt」和包含(無結束行):

19dcd640-0da7-4b1a-9048-1575ee9c5e39 

這是恕我直言,更好的方式,因爲:

  • 沒有powermock:它是一個強大的工具,但它是有代價的(速度較慢的測試,可以測試奇怪的相互作用
  • 它更可讀/易瞭解