使用Spock和Java Spark测试QueryParams

时间:2018-04-06 19:20:24

标签: java testing spock spark-java

我正在使用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会正确评估,但我无法根据服务器进行测试。

2 个答案:

答案 0 :(得分:1)

我找到了解决方案。当()。thenReturn()是mock.method(param)>>时,Spock与Mockito有类似的功能。 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"
}
}

这可以正确评估。

答案 1 :(得分:0)

我坚持批评你的考试。它没有意义,因为您只是测试该方法Request.queryParams(String)返回您定义的值,以便您的模拟或存根返回。此外,您使用受包保护的构造函数创建Request,该构造函数仅在您使用Groovy时才有效。以下是被测课程的相关部分:

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);
  }

  // (...)
}

请参阅?您只是测试模拟可以返回模拟结果。那你为什么要对第三方课程进行单元测试呢?这没有任何意义,除非你的示例代码不是你真正的测试,而只是一个更大的测试的一小部分,你实际上正在测试其他东西(你自己的一个类),只需要模拟结果的其他东西。但是如上所述,测试只是无稽之谈。

无论如何,对于它的价值,有关你的测试结构的一些提示:

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

  • 您有两个测试用例,但只发布了其中一个测试用例的答案,但即使是之前遇到问题的答案也没有。

  • 两个测试用例的结构也非常相似,唯一不同的是RouteMatch的请求URI。对于这种情况,我建议您使用where:@Unroll进行参数化测试。它摆脱了重复的代码,并为测试提供了一些重命名,变量名更具可读性。

package de.scrum_master.stackoverflow

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(),都取决于您。