使用 Spock 和 Java Spark 测试 QueryParams
Test QueryParams with Spock and Java Spark
我正在与 Java Spark 和 Groovy Spock 一起进行测试。我目前正在尝试从 URI 测试 queryParams,但我似乎无法弄明白。
实际上我有一些测试用于测试路径参数,如下所示:
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1" , "text/html")
request = new Request(match, servletRequest)
when:
def test = request.params("id")
then:
test == "1"
}
}
Spark Request使用changeMatch方法,从'/'中的RouteMatch中拆分第一个URI字符串和第二个URI字符串,比较并获取与以':'开头的拆分部分位置匹配的参数
完美,测试结果为 1。
现在,当我尝试测试 queryParams
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1?test=test" , "text/html")
request = new Request(match, servletRequest)
when:
def test = request.queryParams("test")
then:
test == "test"
}
}
测试始终为空。
我的问题是我应该如何正确测试 queryParams?
我想补充一点,当我 运行 在本地尝试时,queryParams 可以正确评估,但我无法根据服务器进行测试。
我找到了解决办法。 Spock 具有与 Mockito when().thenReturn() 类似的功能,即 mock.method(param) >> wantedResult
所以测试看起来像这样:
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1" , "text/html")
request = new Request(match, servletRequest)
when:
servletRequest.getParameter("test") >> "test"
def test = request.queryParams("test")
then:
test == "test"
}
}
这评估正确。
我维持对你的测试的批评。这是没有意义的,因为您只是在测试该方法 Request.queryParams(String)
returns 您定义为由模拟或存根 return 编辑的值。此外,您使用受包保护的构造函数创建 Request
,这仅在您使用 Groovy 时有效。这是被测 class 的相关部分:
package spark;
// (...)
public class Request {
// (...)
private HttpServletRequest servletRequest;
// (...)
Request(RouteMatch match, HttpServletRequest request) {
this.servletRequest = request;
changeMatch(match);
}
public String queryParams(String queryParam) {
return servletRequest.getParameter(queryParam);
}
// (...)
}
看到了吗?您只是在测试模拟可以 return 模拟结果。为什么要对第三方进行单元测试 class?这毫无意义,除非您的示例代码不是您的真实测试,而只是更大测试的一小部分,并且您实际上正在测试其他东西(您自己的 classes 之一)并且只需要模拟结果别的东西。但正如给出的那样,测试只是废话。
无论如何,关于它的价值,关于你的测试结构的一些提示:
为什么要用@Shared
? Spock 的美妙之处在于默认情况下不共享实例变量,以避免测试之间的副作用和依赖性。更糟糕的是,除非您完全删除 @Shared
,否则您自己接受的解决方案中的代码会失败。我试过。你应该更加谨慎地发布你自己的问题的答案,这些问题甚至不起作用,然后甚至接受它们。
您有两个测试用例,但只发布了其中一个的答案,甚至没有发布您之前遇到问题的那个。
这两个测试用例在结构上也非常相似,唯一不同的是RouteMatch
的请求URI。对于这种情况,我建议您使用 where:
和 @Unroll
的参数化测试。它摆脱了重复的代码,并为测试和变量名称进行了一些重命名,使其更具可读性。
package de.scrum_master.Whosebug
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Specification
import spock.lang.Unroll
import javax.servlet.http.HttpServletRequest
class SparkJavaTest extends Specification {
@Unroll
def "Request returns expected value for query parameter '#requestUri'"() {
given:
def routeMatch = new RouteMatch(null, "/charges/:id", requestUri, "text/html")
def servletRequest = Stub(HttpServletRequest) {
getParameter("test") >> "test"
}
def request = new Request(routeMatch, servletRequest)
expect:
request.queryParams("test") == "test"
where:
requestUri << ["/charges/1", "/charges/1?test=test"]
}
}
顺便说一句,您在上面的示例中使用 Mock()
还是 Stub()
取决于您。
我正在与 Java Spark 和 Groovy Spock 一起进行测试。我目前正在尝试从 URI 测试 queryParams,但我似乎无法弄明白。
实际上我有一些测试用于测试路径参数,如下所示:
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1" , "text/html")
request = new Request(match, servletRequest)
when:
def test = request.params("id")
then:
test == "1"
}
}
Spark Request使用changeMatch方法,从'/'中的RouteMatch中拆分第一个URI字符串和第二个URI字符串,比较并获取与以':'开头的拆分部分位置匹配的参数
完美,测试结果为 1。
现在,当我尝试测试 queryParams
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1?test=test" , "text/html")
request = new Request(match, servletRequest)
when:
def test = request.queryParams("test")
then:
test == "test"
}
}
测试始终为空。
我的问题是我应该如何正确测试 queryParams?
我想补充一点,当我 运行 在本地尝试时,queryParams 可以正确评估,但我无法根据服务器进行测试。
我找到了解决办法。 Spock 具有与 Mockito when().thenReturn() 类似的功能,即 mock.method(param) >> wantedResult
所以测试看起来像这样:
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Shared
import spock.lang.Specification
class ChargeRouterValidatorSpec extends Specification {
@Shared
HttpServletRequest servletRequest = Mock(HttpServletRequest.class)
@Shared
Request request
void "test"() {
given:
RouteMatch match = new RouteMatch(null, "/charges/:id", "/charges/1" , "text/html")
request = new Request(match, servletRequest)
when:
servletRequest.getParameter("test") >> "test"
def test = request.queryParams("test")
then:
test == "test"
}
}
这评估正确。
我维持对你的测试的批评。这是没有意义的,因为您只是在测试该方法 Request.queryParams(String)
returns 您定义为由模拟或存根 return 编辑的值。此外,您使用受包保护的构造函数创建 Request
,这仅在您使用 Groovy 时有效。这是被测 class 的相关部分:
package spark;
// (...)
public class Request {
// (...)
private HttpServletRequest servletRequest;
// (...)
Request(RouteMatch match, HttpServletRequest request) {
this.servletRequest = request;
changeMatch(match);
}
public String queryParams(String queryParam) {
return servletRequest.getParameter(queryParam);
}
// (...)
}
看到了吗?您只是在测试模拟可以 return 模拟结果。为什么要对第三方进行单元测试 class?这毫无意义,除非您的示例代码不是您的真实测试,而只是更大测试的一小部分,并且您实际上正在测试其他东西(您自己的 classes 之一)并且只需要模拟结果别的东西。但正如给出的那样,测试只是废话。
无论如何,关于它的价值,关于你的测试结构的一些提示:
为什么要用
@Shared
? Spock 的美妙之处在于默认情况下不共享实例变量,以避免测试之间的副作用和依赖性。更糟糕的是,除非您完全删除@Shared
,否则您自己接受的解决方案中的代码会失败。我试过。你应该更加谨慎地发布你自己的问题的答案,这些问题甚至不起作用,然后甚至接受它们。您有两个测试用例,但只发布了其中一个的答案,甚至没有发布您之前遇到问题的那个。
这两个测试用例在结构上也非常相似,唯一不同的是
RouteMatch
的请求URI。对于这种情况,我建议您使用where:
和@Unroll
的参数化测试。它摆脱了重复的代码,并为测试和变量名称进行了一些重命名,使其更具可读性。
package de.scrum_master.Whosebug
import spark.Request
import spark.routematch.RouteMatch
import spock.lang.Specification
import spock.lang.Unroll
import javax.servlet.http.HttpServletRequest
class SparkJavaTest extends Specification {
@Unroll
def "Request returns expected value for query parameter '#requestUri'"() {
given:
def routeMatch = new RouteMatch(null, "/charges/:id", requestUri, "text/html")
def servletRequest = Stub(HttpServletRequest) {
getParameter("test") >> "test"
}
def request = new Request(routeMatch, servletRequest)
expect:
request.queryParams("test") == "test"
where:
requestUri << ["/charges/1", "/charges/1?test=test"]
}
}
顺便说一句,您在上面的示例中使用 Mock()
还是 Stub()
取决于您。