0

FTP 操作に共通するメソッドを再グループ化するための基本クラスとして使用するクラス FTPOperation があります。これらのメソッドの 1 つが connect() です。

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() 呼び出しが特定の例外を返すさまざまなケースをテストすることを考えましたが、API を介さずに connect() メソッドの実装を知ってテストしているため、間違っていると思います。私が行ったテストの例:

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

    downloadInitialFileTasklet.connect();
}

誰かがこの方法をテストする正しい方法を説明してもらえますか?

ありがとう

4

2 に答える 2

1

本番環境で使用する新しいクラスにラップするよりも、FtpClient クラスのインターフェイスを作成します。

テストの代わりに、スタブ (偽のクラス) またはラップされた FtpClient のモック オブジェクトを実装できます (私は最初の方法を好みます)。

IFtpClient インターフェイスを FtpOperation クラスのコンストラクターに渡します。

于 2012-05-15T08:00:24.747 に答える
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();
}
于 2012-05-15T12:16:38.180 に答える