模拟最终类及其抛出异常的方法

时间:2016-01-13 14:34:46

标签: java unit-testing mockito

我有一个最后一个类,它尝试使用openConnection()连接到提供的URL。我嘲笑它让它返回UnknownHostException,因为我知道提供的URL是未知的,并且还减少了单元测试的时间(对于这一个测试,> 0.01秒太长了。)

要测试的课程:

public final class Server {
    private Server() {}

    public static void getServerStuff(final URL url) throws IOException {
        try {
            final URLConn urlConn;
            // immediately throw exception without trying to make a connection
            urlConn = url.openConnection(); 
        }
        catch (Exception e) {
            // not relevant
        }
    }
}

单元测试

public class ServerTest {

    public class UrlWrapper {

        Url url;

        public UrlWrapper(String spec) throws MalformedURLException {
        url = new URL(spec);
        }

        public URLConnection openConnection() throws IOException {
          return url.openConnection();
        }
    }

    public void testUnknownHostExceptionIsThrown() throws IOException {

        UrlWrapper mockUrl = mock(UrlWrapper.class);
        URLConnection mockUrlConn = mock(URLConnection.class);

        when(mockUrl.openConnection()).thenThrow(UnknownHostException.class);

        final String server = "blabla";
        final URL url = new URL("http://" + server);
        mockUrl.url = url;

        try {
            Server.getServerStuff(mockUrl.url);
        }
        catch (IOException e) {
            // do stuff with Assert
        }
    }
}

我需要使用mockito而不是powermockito,它可以模拟最终的类。我的主要问题是我不知道如何告诉单元测试使用我的模拟openConnection()。它应该仍然测试我的getServerStuff()方法但抛出异常而不实际尝试连接。

我需要更改什么才能使其正常工作?

编辑:我不认为它与引用的问题重复,因为我知道如何模拟最终的类(使用包装器,例如)。我的问题是下一步,这意味着如何使用我的模拟方法。我的单元测试将进入待测试方法并使用标准库中的openConnection(),但我希望它使用我的模拟方法来减少完成单元测试所需的时间。

1 个答案:

答案 0 :(得分:2)

将包裹的UrlWrapper对象传递给URL时,Server的目的是什么?

我假设您可以修改Server

我个人会创建一个新的接口,传递给你的Server#getServerStuff(..)方法。然后,您可以模拟界面以提供所需的模拟行为。

public interface ServerRemote {
    public InputStream getInput() throws IOException
}

public class URLServerRemote implements ServerRemote {

    private URL url;

    public URLServerRemote(URL url) {
        this.url = url;
    }

    public InputStream getInputStream() throws IOException {
        return url.openConnection().getInputStream();
    }
}

public final class Server {
    private Server() {}

    public static void getServerStuff(final ServerRemote remote) throws IOException {
        try {
            final InputStream input;
            // immediately throw exception without trying to make a connection
            input = remote.getInputStream();
        }
        catch (Exception e) {
            // not relevant
        }
    }
}

...

public void testUnknownHostExceptionIsThrown() throws IOException {

    ServerRemote mockServerRemote = mock(ServerRemote.class);
    when(mockServerRemote.getInputStream()).thenThrow(UnknownHostException.class);

    try {
        Server.getServerStuff(mockServerRemote);
    }
    catch (IOException e) {
        // do stuff with Assert
    }
}

...

如果您无法更改Server课程,那么除非您使用PowerMock,否则您将被卡住。