2012-05-15 32 views
0

我有一個類FTPOperation,我用它作爲基類來重新組合FTP操作通用的方法。其中一種方法是connect()。在這種情況下如何通過API進行單元測試?

public abstract class FtpOperation { 

    protected static final Log log = LogFactory.getLog(FtpOperation.class); 

    /** 
    * Hostname or IP address of the FTP server (e.g. localhost, 127.0.0.1). 
    */ 
    private String hostName; 

    private String username; 

    private String password; 

    protected FTPClient ftpClient = getFTPClient(); 

    public void setHostName(String hostName) { 
     this.hostName = hostName; 
    } 

    public void setUsername(String username) { 
     this.username = username; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    /** 
    * Connect to the specified FTP server. 
    * 
    * @throws Exception 
    */ 
    protected void connect() throws Exception { 
     int reply; 

     // Connect to the FTP server 
     ftpClient.connect(hostName); 
     if (!ftpClient.login(username, password)) 
      throw new Exception("Fail to log in with the given credentials."); 

     log.info("Connected to " + hostName + "."); 
     log.info(ftpClient.getReplyString()); 

     // Check if the connection succeeded 
     reply = ftpClient.getReplyCode(); 
     if (!FTPReply.isPositiveCompletion(reply)) 
      throw new Exception("Connection to FTP server failed with code " 
        + reply + "."); 
    } 

     /** 
    * Used for mocking. 
    * 
    * @return 
    */ 
    protected FTPClient getFTPClient() { 
     if (this.ftpClient == null) 
      this.ftpClient = new FTPClient(); 
     return ftpClient; 
    } 
} 

我想寫測試這種方法的單元測試,但我不知道如何測試它。我使用Mockito爲FTPClient實例創建一個模擬對象。 首先,我想過測試ftpClient.connect()調用返回某個異常的不同情況,但我認爲這是錯誤的,因爲我通過知道connect()方法的實現而不是通過API進行測試。 在示例測試中我做:

@Test(expected = SocketException.class) 
public void testConnectSocketException() throws Exception { 
    downloadInitialFileTasklet.setHostName("hostname"); 
    doThrow(new SocketException()).when(mockFtpClient).connect("hostname"); 

    downloadInitialFileTasklet.connect(); 
} 

有人能解釋我來測試這種方法的正確方法?

感謝

回答

1

您的測試意味着要測試什麼?如果你只是看到SocketException沒有被捕獲,那麼看起來有點奇怪的測試。

如果你要包裝異常,那麼它會更有意義。 例如。

protected void connect() throws FTPException { 
    int reply; 

    // Connect to the FTP server 
    try { 
     ftpClient.connect(hostName); 
    } catch (IOException e) { 
     throw new FTPException(e, "unable to connect to: "+hostname); 
    } 
    ... 
} 

通過測試我們正在測試連接早期正確終止,並拋出一個FTPException如果底層的客戶端無法連接

@Test(expected = FTPException.class) 
public void ConnectFailsIfExceptionOnClientConnect() throws FTPException { 
    // setup 
    downloadInitialFileTasklet.setHostName("hostname"); 
    when(mockFtpClient).connect(any(String.class)).doThrow(new SocketException()); 

    // verify -- if something else throws an FTP exception later then the verify 
    // statements should fail the test because either connect was not called 
    // because or login was 
    verify(mockFtpClient).connect(any(String.class)); 
    verify(mockFtpClient, never()).login(any(String.class), any(String.class)); 

    downloadInitialFileTasklet.connect(); 
} 
1

創建的FtpClient類的接口,不是把它包裝成您將在生產環境中使用的新類。

對於測試,您可以實現一個存根(僞類)或包裝的FtpClient的模擬對象(我更喜歡第一種方式)。

將IFtpClient接口傳遞給FtpOperation類的構造函數。

+0

謝謝您的回答。你能提供一個例子嗎? –

+0

我有一個硬件測試的例子,但它在C#中。你要嗎? –