【问题标题】:Mock final classes and its method to throw exceptions模拟最终类及其引发异常的方法
【发布时间】:2016-04-18 14:02:39
【问题描述】:

我有一个最终类,它尝试使用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(),但我希望它使用我模拟的方法来减少完成此单元测试所需的时间。

【问题讨论】:

标签: java unit-testing mockito


【解决方案1】:

当您将包装好的URL 对象传递给Server 时,UrlWrapper 的用途是什么?

我假设您可以编辑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,否则您将被卡住。

【讨论】:

    猜你喜欢
    • 2014-02-15
    • 1970-01-01
    • 2021-04-12
    • 1970-01-01
    • 2013-03-09
    • 2015-03-08
    • 2020-01-13
    • 2011-04-17
    相关资源
    最近更新 更多