如何使MockFTPServer抛出异常

时间:2012-11-06 01:18:11

标签: java unit-testing ftp mocking

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

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

在一个特定的情况下,我正在尝试使用看起来像这样的测试用例来测试我的“connect”方法:

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服务器已关闭。我想确保在这种情况下,我的软件会做出适当的响应。我在模拟FTP服务器站点中找到了关于“自定义命令处理程序”的信息,但我无法弄清楚如何使一个抛出异常。这就是我所拥有的:

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对象,但我无法从文档中弄清楚如何获取有效的对象。有谁知道如何解决这个问题?

感谢。

1 个答案:

答案 0 :(得分:2)

由于没有人在这里刺,我打算试一试。我之前从未使用过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);
}

我知道你想测试SocketException引发的SocketClient.connect()异常...而这一点在这里有点棘手。根据{{​​3}},我相信你正在为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);
}