To support future changes in REST API that that allows query the database using /query endpoint and uses JSON as data format for I/O starting to write down test cases.
My configs are:-
I'm concerned if we have some good support from Spock for writing test cases for SQL injections verification and up to what level generic it can be made.
When we say generic, it means that it should be hitting a different endpoint each time it is run. For example,
1st run : /api/users/query
2nd run : /api/group/query
3rd run : /api/users/query
.
.
nth time : /api/specs/query
So, the domain chosen must be different each time. We can have some random number generated which can be used to identify Domain endpoint from a map or list of query endpoint urls for all domains.
But next thought comes to my mind is whether there could another test case in place that can call these test cases(that check for SQL injections for different endpoints on each run) a specified number of times to test it further and more accurately.
For hitting a different endpoint each time what you can do is create a list of URLMappings and can fetch a random controller each time from list.
If you are not using custom urlmappings then you can iterate over all controller classes and can fetch their actions. But as you have a rest api, I'm assuming you have custom mappings defined in URLMappings.groovy
file. In this case with the help of UrlMappingsArtefactHandler
you can get the url mappings artifacts. Code for that would be:
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
}
Then to fetch url patterns for a specific action from all mappings you can iterate over the result returned from above method using below method:
private List<String> getMappingForAction(List<UrlMapping> mappings, String action){
return mappings.findAll {
UrlMapping mapping ->
return mapping.actionName.equals(action)
}*.urlData.urlPattern
}
And using java.util.Random class you can fetch a random endpoint each time:
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]