如何在spock框架中模拟HttpURLConnection及其responseCode

问题描述 投票:0回答:1

我正在使用Java并使用groovy中的spock框架编写junit,想要模拟HttpUrlConnection并根据不同情况设置connection.getResponseCode() >> 200。

URL url = new URL(proxySettingDTO.getTestUrl());
HttpURLConnection connection = (HttpURLConnection) url.openConnection(proxy);
connection.setRequestMethod("GET");
connection.setUseCaches(false);
...
LOGGER.debug("Response code ::{} ",connection.getResponseCode()); //200 or 403

我尝试过使用

HttpURLConnection httpURLConnection = Mock()
URL url = new URL(proxySettingDTO.getTestUrl());
url.openConnection(_) >> httpURLConnection

但是它不起作用。

java groovy junit mocking spock
1个回答
2
投票

您的问题有几处错误:

  1. url.openConnection(_) >> httpURLConnection
    中,您尝试存根方法结果,但您的
    URL
    对象未声明为模拟、存根或间谍。也就是说,你的尝试注定会失败。

  2. 即使您尝试模拟

    URL
    ,该 JDK 类也是最终的,即您无法模拟它,因为模拟是子类。

  3. 被测试的类通过调用

    HttpURLConnection
    来获取
    url.openConnection(proxy)
    。由于 (3),该方法不可模拟,因此您应该将连接创建外部化到辅助类中
    ConnectionManager
    ,然后将模拟实例注入到被测试的类中以使其可测试。

一般来说,测试是一种设计工具,而不仅仅是用测试来覆盖代码。如果测试很困难,则意味着组件设计耦合得太紧。让测试帮助使用 TDD(测试驱动开发)或至少测试驱动重构来驱动您的设计,即使后者有点晚了并且意味着返工。如果您进一步解耦组件,例如通过不创建您的类在内部依赖的对象实例,但允许 API 用户注入它们,例如通过构造函数或设置器,可测试性会更好,并且您会遇到更少的麻烦。

这个怎么样?

class UnderTest {
  private Proxy proxy
  private ProxySettingDTO proxySettingDTO
  private ConnectionManager connectionManager
   UnderTest(Proxy proxy, ProxySettingDTO proxySettingDTO, ConnectionManager connectionManager) {
    this.proxy = proxy
    this.proxySettingDTO = proxySettingDTO
    this.connectionManager = connectionManager
  }

  int getConnectionResponseCode() {
    URL url = new URL(proxySettingDTO.getTestUrl())
    HttpURLConnection connection = (HttpURLConnection) connectionManager.openConnection(url, proxy)
    connection.setRequestMethod("GET")
    connection.setUseCaches(false)
    connection.getResponseCode()
  }
}
class ProxySettingDTO {
  String getTestUrl() {
    "https://scrum-master.de"
  }
}
class ConnectionManager {
  URLConnection openConnection(URL url, Proxy proxy) {
    url.openConnection(proxy)
  }
}
package de.scrum_master.stackoverflow.q71616286

import spock.lang.Specification

class HttpConnectionMockTest extends Specification {
  def test() {
    given: "a mock connection manager, returning a mock connection with a predefined response code"
    ConnectionManager connectionManager = Mock() {
      openConnection(_, _) >> Mock(HttpURLConnection) {
        getResponseCode() >> 200
      }
    }

    and: "an object under test using mock proxy, real DTO and mock connection manager"
    def underTest = new UnderTest(Mock(Proxy), new ProxySettingDTO(), connectionManager)

    expect: "method under test returns expected response"
    underTest.getConnectionResponseCode() == 200
  }
}

在 Groovy Web 控制台中尝试一下。

© www.soinside.com 2019 - 2024. All rights reserved.