使用Spock和Java Spark测试QueryParams

使用Spock和Java Spark测试QueryParams,java,testing,spock,spark-java,Java,Testing,Spock,Spark Java,我正在使用JavaSpark和GroovySpock进行测试。我目前正试图从一个URI测试queryParams,但我似乎无法理解它 实际上,我有一些测试用于测试路径参数,如下所示: import spark.Request import spark.routematch.RouteMatch import spock.lang.Shared import spock.lang.Specification class ChargeRouterValidatorSpec extends Spec

我正在使用JavaSpark和GroovySpock进行测试。我目前正试图从一个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"
    }
}
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"
}
}
Spark请求使用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的函数与mockitowhen.thenReturn类似,后者是mock.methodparam>>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:
        def test = request.params("id")

        then:
        test == "1"
    }
}
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.queryParamsString返回您定义的由模拟或存根返回的值。此外,您可以使用包保护的构造函数创建请求,因为您使用的是Groovy,所以该构造函数才有效。以下是被测课程的相关部分:

包装火花; // ... 公共类请求{ // ... 私有HttpServletRequest-servletRequest; // ... RequestRouteMatch匹配,HttpServletRequest请求{ this.servletRequest=请求; 变化匹配; } 公共字符串queryParamsString queryParam{ 返回servletRequest.getParameterqueryParam; } // ... } 看到了吗?您只是在测试mock是否可以返回mock结果。那你为什么还要对第三方类进行单元测试呢?这毫无意义,除非您的示例代码不是真正的测试,而是更大测试的一小部分,并且您实际上是在测试您自己的类中的其他东西,并且只需要其他东西的模拟结果。但正如所说的,这项测试只是胡说八道

无论如何,关于您的测试结构,值得一提的是:

为什么要使用@Shared?Spock的优点在于默认情况下不共享实例变量,以避免测试之间的副作用和依赖关系。更糟糕的是,除非您完全删除@Shared,否则您自己接受的解决方案中的代码将失败。我试过了。你应该更加谨慎地回答你自己的问题,这些问题甚至不起作用,然后甚至接受它们

您有两个测试用例,但只发布了其中一个的答案,甚至没有发布您以前遇到问题的答案

这两个测试用例在结构上也非常相似,唯一不同的是RouteMatch的请求URI。我建议您在这种情况下使用带有where:和@Unroll的参数化测试。它消除了重复代码,并对测试和变量名进行了一些重命名,因此可读性更强

包de.scrum\u master.stackoverflow 导入火花。请求 导入spark.routematch.routematch 导入spock.lang.Specification 导入spock.lang.Unroll 导入javax.servlet.http.HttpServletRequest 类SparkJavaTest扩展了规范{ @展开 def请求返回查询参数“requestUri”的预期值{ 鉴于: def routeMatch=new RouteMatchnull,/charges/:id,requestUri,text/html def servletRequest=StubHttpServletRequest{ getParametertest>>测试 } def request=新请求路由匹配,servletRequest 期望: request.queryParamstest==测试 哪里:
requestUri欢迎来到SO!:-这个问题是关于,而不是关于Apache Spark。我已经修复了您的错误问题标签。也许现在您将得到一个答案。还有两件事:1请将您的问题更改为。由于从代码段中切断了导入,您只能猜测您正在使用的框架。2这绝对不是测试或Spock问题,你显然在问有关Spark Java API的问题。@kriegaex谢谢你的提示,我已经编辑了它,显示了导入内容。至于2,我知道它不是直接的Spock,但让人们知道我在使用它,也许他们可以想出一个“Spock-oriented”solution@SebastianKondek-如果queryParams在本地正确计算,则表示est功能正常。您是否尝试打印并播放request.contextPath和request.host以查看本地测试和远程测试之间的差异?@SHG感谢您的评论。我找到了一个解决方法。至于您的问题,我尝试过,在远程运行测试时,这两个都为空。这应该是什么类型的测试?您是成功测试您的模拟是否返回模拟结果。之前您说过要测试case/charges/1?test=test,这不是您在代码中要做的。事实上,正如您已经注意到的,Spark Java不会返回您期望的结果。因此,在我看来,您是在欺骗自己相信
我们的应用程序通过调整一个不相关的测试来通过测试。也许你想重新调查和分析一下?@kriegaex实际上是一样的,因为在/charges/1?test=test的情况下,我希望Spark处理test queryParam,他是通过servletRequest.getParameter完成的。在第一个示例中,正如SHG在注释中所说的,request.ContextPath和request.hostpath都为null,因此我认为正是出于这个原因,没有对mu URI进行评估。通过模拟URI在正常情况下使用的方法的答案,并返回应该在测试用例/charges/1中发送的值?test=test对我来说似乎是正确的。@kriegaex同样,这只是一个简单的场景。实际场景还将在后台服务器中进行测试,其中request.ContextPath和request.host不为null,Spark可以在URI中正确处理queryParams,但此处发布的测试失败。你没有理由使用@Shared,所以我只是删除了注释。只有到那时它才会过去。首先谢谢你的时间。现在,我可能忘了写它,但是,是的,这是一个更好地反映我的问题的测试用例。这个测试实际上是一个更大的范围,我正在测试我自己的方法,它对收到的请求进行一些验证。其中一些验证正在检查queryParams,我没有测试它,因为Spark无法在服务器上下文之外正确处理请求。为什么要使用@Shared?正如我上面所说的,这是一个更大的上下文,所以这不是我需要Request和HttpServlerRequest的唯一测试用例,这就是为什么我使用它作为共享资源。我有两个测试用例。如果我理解正确,我有两个例子。第一个显示Spark.paramsworks正确,第二个显示Spark.QueryParams在测试中失败的问题。我仍然不熟悉斯波克,所以我很感激最后的提示。此外,我提供的解决方案在我的项目中编译并运行得非常完美。我简直不敢相信,我真的检查过了。无论如何,不要使用@Shared。创建一个模拟是很便宜的,而且在测试中为另一个变量赋值也是很便宜的。您不必节省时间,只需将上下文插入另一个功能方法。这不值得冒险,因为没有收益。您希望避免方法之间的相互依赖性和副作用。相信我,我在测试方面有一点经验。选择干净的代码。谢谢你的提示,我会研究它并进行重构