在这种情况下如何使用模拟?

时间:2015-04-29 05:33:59

标签: unit-testing mocking

这是我的问题:

这是我尝试编写测试用例的方法。

此方法尝试创建" HttpClient"的实例。但是我这边的服务器不可用。

所以我试图通过使用模拟实现这一点,但我没有成功。

所以有人能告诉我该怎么做?

以下是方法:

  public boolean callGet(final boolean keepResult) {
            boolean ok = false;
            if (url != null) {
                try {
                    log.appendLine("Url:");
                    log.append(url);
                    final HttpClient client = new HttpClient();
                    setAuthentication(client);
                    final GetMethod method = new GetMethod(url);
                    if (Utils.isFilled(userAgent)) {
                        method.setRequestHeader("User-Agent", userAgent);

                    }
                    status = client.executeMethod(method);
                    ok = (status == HttpStatus.SC_OK);
                    log.appendLine("Status http call:");
                    log.append(status);
                    if (ok) {
                        if (keepResult) {
                            if (maxSizeResult > 0) {
                                result = method
                                        .getResponseBodyAsString(maxSizeResult);

                            } else {
                                result = method.getResponseBodyAsString();

                            }
                        }
                    }
                } catch (final Exception e) {
                }
            }
            return ok;

这是我的单元测试方法:

   @Before
        public void start() {
            urlcaller = new UrlCaller();
            UrlCaller mock1 = Mockito.mock(UrlCaller.class);
            Mockito.when(mock1.callGet(true)).thenReturn(true);

        }

        @Test
        public void testSetUserAgent() throws HttpException, IOException {

        boolean t1 = urlcaller.callGet(true);

        System.out.println(t1);

    }

}

这是我得到的错误:

Problem:
    UrlCaller.java
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946)
        ...
        at de.bcode.utilsWithLog.UrlCaller.callGet(UrlCaller.java:115)
        at de.bcode.utilsWithLog.TestUrlCaller.testSetUserAgent(TestUrlCaller.java:52)
    Caused by:
        java.io.EOFException: SSL peer shut down incorrectly
            at sun.security.ssl.InputRecord.read(InputRecord.java:482)
            ...
            at de.bcode.utilsWithLog.UrlCaller.callGet(UrlCaller.java:115)
            at de.bcode.utilsWithLog.TestUrlCaller.testSetUserAgent(TestUrlCaller.java:52)
false

感谢您阅读所有问题:-)希望它足够清楚。

2 个答案:

答案 0 :(得分:2)

您当前的方法存在一些问题:

在隔离测试另一个类时,通常使用mocks / stubs / fakes / whatever,即提供协作者类的伪实现。 例如,您可以单独测试某个控制器并为其每个协作对象(假存储库,假UrlCaller,...)提供模拟。这样,您可以单独测试被测系统(=控制器)的实际生产代码,而不依赖于其协作者的正确运行。

您的测试会创建UrlCaller类的真实对象和假对象,然后继续练习真正的urlcaller对象。这意味着所有实际的生产代码都会被触发,并且创建的模拟URL调用者很乐意无所事事。

我在这些情况下通常做的是:

  • 弄清楚UrlCaller类的唯一责任
  • 如果它有任何难以测试/外部依赖(如真正的HTTP流量),将它们分成一个新类并提供一些用假替换这个协作对象的方法(你可以通过使用构造函数注入或子类来做到这一点)测试模式,例如)
  • 在生产代码中为协作者提供生产实施
  • 在您的测试代码中提供一个虚假的实现来测试您正在测试的系统,而不需要那些讨厌的外部依赖。

对于你的具体情况:似乎外部依赖使得这个代码难以测试的是HttpClient。尝试从UrlCaller中提取对此类的依赖性。如果这对您来说似乎没有实际意义(“但是UrlCaller类不会做任何事情”),我会放弃单独测试UrlCaller类的冲动,只依赖于进行真正http调用的集成测试

答案 1 :(得分:0)

你的测试没有多大意义。您可以创建一个模拟并在测试中调用模拟。

通常你这样做:

  • 创建模拟(最好是界面)
  • 将模拟器注入您的待测单元
  • 致电您的设备

我认为您应该将要模拟的部分与要测试的代码分开,并通过接口注入模拟部分。