SQL 注入的 Grails Spock 编写单元/集成测试用例

Grails Spock writing unit / integration test case for SQL injections

为了支持 REST API 中的未来更改,允许使用 /query 端点查询数据库并使用 JSON 作为 I/O 开始编写测试用例的数据格式。

我的配置是:-

  1. Grails 2.3.8
  2. Spock 测试框架

我担心我们是否能从 Spock 那里得到一些很好的支持来编写 SQL 注入验证的测试用例,以及它可以达到什么级别的通用性。

当我们说通用时,这意味着它应该在每次 运行 时到达不同的端点。 例如,

1st run : /api/users/query 
2nd run : /api/group/query
3rd run : /api/users/query
.
.
nth time : /api/specs/query

因此,每次选择的域必须不同。我们可以生成一些随机数,这些随机数可用于从地图或所有域的查询端点 url 列表中识别域端点。

但我接下来想到的是是否可以有另一个测试用例可以调用这些测试用例(检查每个 运行 上不同端点的 SQL 注入)指定测试的次数越多越准确。

如果您想要 运行 使用 Spock 的一系列参数从一个测试执行更改为下一个测试执行的相同测试,那么您应该考虑使用 parameterization using Spock where blocks.

下面显示的示例来自 Spock 文档,但您可以轻松地将参数更改为您希望测试的端点数组。

def "computing the maximum of two numbers"() {
  expect:
  Math.max(a, b) == c

  where:
  a << [5, 3]
  b << [1, 9]
  c << [5, 9]
}

为了每次访问不同的端点,您可以做的是创建一个 URLMappings 列表,并且每次都可以从列表中获取一个随机控制器。

如果您不使用自定义 url 映射,那么您可以遍历所有控制器 class 并获取它们的操作。但是当你休息 api 时,我假设你在 URLMappings.groovy 文件中定义了自定义映射。在这种情况下,在 UrlMappingsArtefactHandler 的帮助下,您可以获得 url 映射工件。代码为:

import org.codehaus.groovy.grails.commons.UrlMappingsArtefactHandler
import org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingEvaluator
import org.codehaus.groovy.grails.web.mapping.UrlMapping
import org.springframework.mock.web.MockServletContext

private List<UrlMapping> getAllURLMappings(){
    ClassLoader classLoader = this.class.classLoader
    def mappings = grailsApplication.getArtefacts(UrlMappingsArtefactHandler.TYPE)

    MockServletContext mctx = classLoader.loadClass('org.springframework.mock.web.MockServletContext').newInstance()
    DefaultUrlMappingEvaluator evaluator = classLoader.loadClass("org.codehaus.groovy.grails.web.mapping.DefaultUrlMappingEvaluator").newInstance(mctx)
    List<UrlMapping> allMappings = []

    List<UrlMapping> grailsClassMappings
    for (mapping in mappings) {
        if (Script.isAssignableFrom(mapping.getClazz())) {
            grailsClassMappings = evaluator.evaluateMappings(mapping.getClazz())
        } else {
            grailsClassMappings = evaluator.evaluateMappings(mapping.getMappingsClosure())
        }
        allMappings.addAll(grailsClassMappings)
    }
    return allMappings
}

然后要从所有映射中获取特定操作的 url 模式,您可以使用以下方法迭代从上述方法返回的结果:

private List<String> getMappingForAction(List<UrlMapping> mappings, String action){
    return mappings.findAll {
        UrlMapping mapping ->
            return mapping.actionName.equals(action)
    }*.urlData.urlPattern
}

并且使用 java.util.Random class 你可以每次获取一个随机端点:

List<UrlMapping> allMappings = getAllURLMappings()
List<String> mappings = getMappingForAction(allMappings, "query")

int size = mappings.size()

Random r = new Random()
int index = r.nextInt(size - 0)

println mappings[index]