gpt4 book ai didi

junit - 如何正确地对从 FTP 服务器获取文件的类进行单元测试

转载 作者:行者123 更新时间:2023-12-03 20:18:08 27 4
gpt4 key购买 nike

其实我的问题分为两部分。

  • 如何将我的测试与外部隔离,但仍确保该功能有效?
  • 如何使用 Mockito 模拟 apache commons FtpClient 类?当我 mock 它时,我在:
  • 处得到空值

    InputStream inputStream = ftpClient.retrieveFileStream(ftpParameters.getSourceFileName());



    这是测试类:

    public class SimpleFtpFileImporterTest {
    FtpParameters ftpParams =new FtpParameters();
    SimpleFtpFileImporter fileImporter=new SimpleFtpFileImporter();
    FTPClient ftpMock= mock(FTPClient.class);



    @Before
    public void startup(){
    this.ftpParams.setServer("10.0.206.126");
    this.ftpParams.setPort(21);
    this.ftpParams.setUserName("mikola");
    this.ftpParams.setPassword("password");
    this.ftpParams.setSourceFileName("readme.txt");
    }


    @Test
    public void returnNullWhenFileCouldNotBeFetchedCompletely() throws IOException{
    when(ftpMock.completePendingCommand()).thenReturn(false);
    fileImporter=new SimpleFtpFileImporter(ftpMock);
    byte[] bytes= fileImporter.downloadFile(ftpParams);
    assertNull(bytes);
    }

    }

    这是被测系统:

    public class SimpleFtpFileImporter implements IFileImporter {

    private FTPClient ftpClient;

    static Logger logger = Logger.getLogger(SimpleFtpFileImporter.class);

    static {
    PropertyConfigurator.configure("config/log4j.properties");
    }

    /**
    * Creates a SimpleFtpFileImporter class instance passing an FtpClient.
    * This constructor helps create unit tests by passing any kind of FTPClient, eg. an http ftp client.
    *
    * @param ftpClient An FTPClient object
    */
    public SimpleFtpFileImporter(FTPClient ftpClient) {
    this.ftpClient = ftpClient;
    }

    public SimpleFtpFileImporter() {

    }
    /**
    * Gets the file specified from the specified FTP server
    *
    * @param ftpParameters An FtpParametrs object that bears the needed information
    * @return File in byte array if successful, otherwise null
    */
    public byte[] downloadFile(FtpParameters ftpParameters) {
    if (this.ftpClient == null)
    this.ftpClient = new FTPClient();
    if (!ftpParameters.isProperlyPopulated()) {
    logger.warn("Not all FTP parameters have been set. Execution will halt.");
    throw new FtpParametersNotSetException("Ftp parameters not properly set.");
    }
    try {
    ftpClient.connect(ftpParameters.getServer());
    ftpClient.login(ftpParameters.getUserName(), ftpParameters.getPassword());
    ftpClient.enterLocalPassiveMode();
    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    logger.info("FTP connection succesfully established. Preparing to retrieve file:"+ftpParameters.getSourceFileName());

    InputStream inputStream = ftpClient.retrieveFileStream(ftpParameters.getSourceFileName());
    if (inputStream != null) {
    byte[] bytes = IOUtils.toByteArray(inputStream);
    boolean success = ftpClient.completePendingCommand();
    logger.info("File received");
    inputStream.close();
    if (success) {
    return bytes;
    } else{
    logger.warn("File fetching process could not be through. Returning null.");
    return null;
    }
    }else{
    logger.warn("Wrong file name specified. File name:"+ftpParameters.getSourceFileName());
    throw new RuntimeException("Wrong file name specified");
    }


    } catch (IOException ex) {
    logger.error("Problem while trying to get file from remote FTP. Message: " + ex.getMessage() + " \n\r" + ex);
    }

    return null;
    }

    }

    尽管我提供了所有需要的参数(主机、端口、用户名和密码),但似乎模拟的 FtpClient 对象不适合制作真实的东西

    最佳答案

    要回答到目前为止可以回答的部分 - 您必须学习如何编写 可测试的 代码;一个很好的起点是这些 videos

    你这边已经有一个误区了:看来mocked的FtpClient对象不适合做真实的东西。

    确切地。模拟是一个 模拟 ,一个空的 测试 stub 。它没有做任何实际的事情。这就是使用模拟的全部意义。它们是空 shell ,除了提供您为它们指定的行为之外什么都不做。
    我的意思是:Mockito 创建的对象是 而不是 一个真正的 FtpClient。它只是一个“看起来”像 FtpClient 的 模拟 。它没有 到“真正的” FtpClient 类的任何 连接。换句话说:是的,您可以调用 FtpClient 具有的方法,但它们都是 (它们什么都不做。它们什么也不做)做你 指定 他们做他们的事情)。

    关键是:您使用模拟将 与外部实现完全解耦 。通过为您的测试代码提供 模拟 ,您可以简单地 忽略 “真实”类正在做的一切。

    查看您的代码和“实际”问题:

    InputStream inputStream = ftpClient.retrieveFileStream(

    为了使这项工作,您必须 配置 您的 模拟 以便在调用 时返回 有用的东西 079104

    我的意思是:你已经这样做了:
    when(ftpMock.completePendingCommand()).thenReturn(false);

    告诉 Mockito:当 retrieveFileStream() 被调用时,返回 completePendingCommand() 。您需要为被测代码调用的每个 方法对 执行此操作!

    除此之外;您的代码有很多问题,例如:
    public SimpleFtpFileImporter() {
    }

    不是 应该是空的;相反,您应该执行以下操作:
    public SimpleFtpFileImporter() {
    this(new FtpClient());
    }

    那里的简单答案:默认情况下,字段应为 final (除非您有充分的理由不将它们设为 final):
    private final FTPClient ftpClient;

    编译器会让 告诉 你忘记初始化那个字段了!在您的情况下,绝对是 没有理由在构造时不初始化该字段。这只会让整个类(class)变得更加复杂和难以测试。

    关于junit - 如何正确地对从 FTP 服务器获取文件的类进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42020170/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com