2017-06-29 125 views
1

我有一個方法,在我的事業:如何嘲笑一個靜態的文件與方法的Mockito

public void createDirectories(final Path root, final Scaffolding scaffolding) throws FileAlreadyExistsException { 
    if (Files.exists(root)) { 
     throw new FileAlreadyExistsException("Root directory " + root.toString() + " already exists."); 
    } else { 
     Files.createDirectories(root); 
     // Create directories from the scaffolding object 
    } 
} 

我想嘲笑Files這樣我就可以測試,以確保Files.createDirectories與預期的領域被稱爲與否。

我可以用Mockito做這個嗎?或者我需要實際創建目錄並檢查它們是否存在於某個tmp文件夾中?

+0

您需要powermockito來模擬靜態方法。 –

+0

您可以使用PowerMockito來做到這一點。雖然fwiw,JUnit的TemporaryFolder旨在幫助進行這種測試。 –

+0

@LucianovanderVeekens它不僅僅是一種靜態方法。這是一個全球課程。'文件'不是我的工具類的一個實例,我可以嘲笑並將它傳遞給類。 – Kousha

回答

0

當你寫TDD的東西並有麻煩將其視爲不良設計的信號。你不需要嘲笑靜態字段或找到一些棘手的庫來做到這一點。而不是做這個代表文件系統的實體,並把與文件操作相關的所有方法都放到這個類中。有了這個重構你的代碼將是這樣的:

class UtilClass { //util classes are bad don't do it 
    private final FileSystem fileSystem; 

    public UtilClass(FileSystem fileSystem) { 
     this.fileSystem = fileSystem; 
    } 


    public void createDirectories(final Path root, final Scaffolding scaffolding) throws FileAlreadyExistsException { 
     if (fileSystem.exists(root)) { 
      throw new FileAlreadyExistsException("Root directory " + root.toString() + " already exists."); 
     } else { 
      fileSystem.createDirectories(root); 
      // Create directories from the scaffolding object 
    } 




interface FileSystem { 

    boolean exists(Path path); 

    void createDirectories(Path path); 
} 

和測試類

class UtilClassTest { 


     @Test(expected = FileAlreadyExistsException.class) 
     public void shouldThrowExceptionWhenRootPathExists() { 
      FileSystem mockFileSystem = Mockito.mock(FileSystem.class); 
      Mockito.when(mockFileSystem.exists(anyPath())).return(true); 
      UtilClass util = new UtilClass(mockFileSystem); 
      util.createDirectories(mock(Path.class), mock(Scaffolding.class)) 
     } 
    } 

在你的代碼之外的測試替代模擬落實。

class FileSystemImpl implements FileSystem { 

    boolean exists(Path path){ 
     return Files.exists(path); 
    } 

    createDirectories(Path path){ 
     return Files.createDirectories(path); 
    } 

} 

並且您不需要在測試或模擬靜態字段中觸摸文件系統。

0

你不能嘲笑基於Mockito的靜態方法,在大多數情況下,你也不應該,特別是Java提供的方法。你可以用PowerMock來模擬靜態方法,但這是一個全局核心庫。

您在此處測試的代碼片段是否在目錄存在時發生異常。如果Files.exists()返回的結果不好,則您的程序會以任一方式敬酒。所以你最終應該測試的是,正確地遵循流程,同時取決於全球實施的全面實施的Files

@Test 
public void testCreateDirectories() { 

    File tempFile = new File("test"); 
    tempFile.delete(); //delete test directory if it exists  
    tempFile.deleteOnExit(); //and again when the test finishes 

    Path testPath = tempFile.getPath(); 

    foo.createDirectories(testPath, mock(Scaffolding.class)); //should create path 
    Assert.assertTrue(tempFile.exists()); 

    try { 
     foo.createDirectories(testPath, mock(Scaffolding.class)); //should FAE 
     Assert.fail(Should have thrown an FAE exception at this point!); 
    } 
    catch(FileAlreadyExistsException faee) { 
     logger.debug("Expected FAE exception thrown", faee); 
    } 
} 

該執行將經過真假路徑並自行清理。

邏輯的這種雙重執行測試兩條路徑,並且如果您的if語句管理爲混淆,則設計爲涵蓋以下方案。

  • 布爾作品像預期一樣:兩個呼叫工作,PASS
  • 布爾意外反轉:第一個呼叫拋出FAE,FAIL
  • 布爾總是返回false:第二個呼叫不會引發FAE,FAIL。
  • 布爾總是返回true:第一個調用拋出FAE,FAIL。
0

你可以使用JUnit的@Rule爲此,它創建測試執行完成後,將被刪除臨時文件夾中(或失敗):

public class TestTemporaryFolderRule { 
    @Rule 
    public TemporaryFolder testFolder = new TemporaryFolder(); 

    @Test 
    public void testInTempFolder() throws IOException { 
     File tempFolder = testFolder.newFolder("test"); 
     // test... 
    } 
} 
+0

這並不回答如何模擬'文件'的問題。 –

+0

@DanW在這種情況下,使用模擬不是測試O.P.問題的最佳方法 – NamshubWriter