如何在 spock 框架中模拟 HttpURLConnection 及其 responseCode
How to mock HttpURLConnection and its responseCode in spock framework
我正在使用 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
但它不起作用。
你的问题有几处错误:
它由一组不连贯的不完整代码片段组成,而不是 MCVE,即一个完整的、最小的示例,每个想要帮助您的人都可以编译和 运行没有做你的工作和自己编造例子 classes。那是你的工作。
在 url.openConnection(_) >> httpURLConnection
中,您试图存根方法结果,但您的 URL
对象未声明为模拟、存根或间谍。也就是说,你的尝试注定要失败。
即使您尝试模拟 URL
,JDK class 也是最终的,即您不能模拟它,因为模拟是子classes.
正在测试的 class 通过调用 url.openConnection(proxy)
获取 HttpURLConnection
。由于 (3),该方法不可模拟,因此您应该将连接创建外部化到辅助程序 class ConnectionManager
中,然后将模拟实例注入被测 class 以进行它可测试。
一般来说,测试是一种设计工具,而不仅仅是用测试覆盖代码。如果测试困难,则意味着组件设计耦合太紧。让测试帮助使用 TDD(test-driven 开发)或至少 test-driven 重构来推动您的设计,即使后者有点晚并且意味着返工。如果你更多地解耦你的组件,例如通过不创建你的 class 内部依赖的对象实例,但允许 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.Whosebug.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
}
}
我正在使用 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
但它不起作用。
你的问题有几处错误:
它由一组不连贯的不完整代码片段组成,而不是 MCVE,即一个完整的、最小的示例,每个想要帮助您的人都可以编译和 运行没有做你的工作和自己编造例子 classes。那是你的工作。
在
url.openConnection(_) >> httpURLConnection
中,您试图存根方法结果,但您的URL
对象未声明为模拟、存根或间谍。也就是说,你的尝试注定要失败。即使您尝试模拟
URL
,JDK class 也是最终的,即您不能模拟它,因为模拟是子classes.正在测试的 class 通过调用
url.openConnection(proxy)
获取HttpURLConnection
。由于 (3),该方法不可模拟,因此您应该将连接创建外部化到辅助程序 classConnectionManager
中,然后将模拟实例注入被测 class 以进行它可测试。
一般来说,测试是一种设计工具,而不仅仅是用测试覆盖代码。如果测试困难,则意味着组件设计耦合太紧。让测试帮助使用 TDD(test-driven 开发)或至少 test-driven 重构来推动您的设计,即使后者有点晚并且意味着返工。如果你更多地解耦你的组件,例如通过不创建你的 class 内部依赖的对象实例,但允许 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.Whosebug.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
}
}