【问题标题】:How to Make MockFTPServer Throw an Exception如何让 MockFTPServer 抛出异常
【发布时间】:2012-11-06 01:18:11
【问题描述】:

我有一些连接到 FTP 服务器的代码,我正在尝试为该代码编写测试用例。为此,我一直在尝试使用 MockFtpServer 模拟 FTP 服务器,以便测试我的交互。

http://mockftpserver.sourceforge.net/index.html

在一种特殊情况下,我正在尝试使用如下所示的测试用例来测试我的“连接”方法:

public class FTPServiceTestWithMock {

    private FakeFtpServer server;
    private FTPService service;
    private int controllerPort;

    @Before
    public void setup() {
        server = new FakeFtpServer();
        server.setServerControlPort(0); // Use free port - will look this up later

        FileSystem fileSystem = new WindowsFakeFileSystem();
        fileSystem.add(new DirectoryEntry("C:\\temp"));
        fileSystem.add(new FileEntry("C:\\temp\\sample.txt", "abc123"));
        server.setFileSystem(fileSystem);
        server.addUserAccount(new UserAccount("user", "pass", "C:\\"));
        server.start();
        controllerPort = server.getServerControlPort();

        service = new FTPService();
    }

    @After
    public void teardown() {
        server.stop();
    }

    @Test
    public void testConnectToFTPServer() throws Exception {
        String testDomain = "testdomain.org";
        String expectedStatus = 
            "Connected to " + testDomain + " on port " + controllerPort;

        assertEquals(
            expectedStatus, 
            service.connectToFTPServer(testDomain, controllerPort)
        );
    }

}

这段代码完美运行——它设置了一个假的 FTP 服务器并对我的代码进行测试,以确保它可以连接并返回适当的消息。

但是,我的 FTP 客户端的 API 规范显示,当我尝试连接时可能会引发异常。

http://commons.apache.org/net/api-3.1/org/apache/commons/net/SocketClient.html#connect%28java.lang.String%29

我想编写第二个测试用例来测试抛出的异常,这可能是域名不正确或 FTP 服务器关闭。我想确保在这种情况下,我的软件能够做出适当的响应。我在 Mock FTP Server 站点中找到了有关“自定义命令处理程序”的信息,但我不知道如何让一个抛出异常。这就是我所拥有的:

public void testConnectToFTPServerConnectionFailed() throws Exception {
    ConnectCommandHandler connectHandler = new ConnectCommandHandler();
    connectHandler.handleCommand(/* Don't know what to put here */);
    server.setCommandHandler(CommandNames.CONNECT, connectHandler);
}

handleCommand 方法需要一个 Command 对象和一个 Session 对象,但我无法从文档中弄清楚如何获取要发送的有效对象。有人知道该怎么做吗?

谢谢。

【问题讨论】:

    标签: java unit-testing ftp mocking


    【解决方案1】:

    由于没有人在这里刺伤,所以我要试一试。我以前从未使用过 MockFtpServer,所以这是我的第一次尝试。

    我认为测试服务器是否关闭的最简单方法是关闭服务器。

    @Test(expected = IOException.class)
    public void testConnectToFTPServer_ServerDown() throws Exception {
        // kill the server
        server.stop();
        service.connectToFTPServer("testdomain.org", controllerPort);
    }
    

    如果你想测试是不是用户名和密码无效,或许你可以把FTP回复码设置为430:-

    @Test(expected = IllegalStateException.class)
    public void testConnectToFTPServer_InvalidUserPassword() throws Exception {
        // assuming you already started it in setup(), you may want to stop it first
        if (server.isStarted()) {
            server.stop();
        }
    
        ConnectCommandHandler connectCommandHandler = (ConnectCommandHandler) server.getCommandHandler(CommandNames.CONNECT);
    
        // 430 = FTP error code for "Invalid username or password"
        connectCommandHandler.setReplyCode(430);
        server.setCommandHandler(CommandNames.CONNECT, connectCommandHandler);
        server.start();
    
        service.connectToFTPServer("testdomain.org", controllerPort);
    }
    

    我知道你想测试SocketClient.connect() 抛出的SocketException 异常...这里有点棘手。基于FTP error codes,我相信您正在寻找 10000 系列错误代码之一(如果我在这里错了,请纠正我,但我不是 FTP 专家)。这个 10000 系列错误代码的问题在于,它会使您的测试无限期地旋转,因为该错误代码指示无法连接远程服务器,因此在针对 MockFtpServer 进行测试时,测试并不真正知道何时停止。因此,在这种情况下,我将测试设置为 5 秒后超时(我认为这是合理的)。当然,你不会在这里得到SocketException,但我认为该行为与实际的实现代码足够接近。

    @Test(timeout = 5000)
    public void testConnectToFTPServer_InvalidHostName() throws Exception {
        // assuming you already started it in setup(), you may want to stop it first
        if (server.isStarted()) {
            server.stop();
        }
    
        ConnectCommandHandler connectCommandHandler = (ConnectCommandHandler) server.getCommandHandler(CommandNames.CONNECT);
    
        // 10060 = FTP error code for "Cannot connect to remote server."
        connectCommandHandler.setReplyCode(10060);
        server.setCommandHandler(CommandNames.CONNECT, connectCommandHandler);
        server.start();
    
        service.connectToFTPServer("testdomain.org", controllerPort);
    }
    

    【讨论】:

    • 感谢您的建议,limc。一些注意事项......首先,您不需要停止服务器来替换 CommandHandler 的功能 - 它只是有助于保持代码更简洁。对于某些事情,例如测试错误的密码,只需发送错误的密码并获得正确的回复代码就很容易了。这样做非常方便的是做一些类似于最终测试的事情,在该测试中,您返回一个 10060 回复代码,表明那里有一个套接字,但不接受连接。
    猜你喜欢
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 2016-12-25
    • 2013-05-24
    • 2014-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多