Friday, February 3, 2012

integration testing with the grails export plugin

currently I'm testing a lot of controllers in my miniX application and run into the issue that it's nearly impossible to test the grails export plugin. Since the setup tends to get more complicated than your actual test.

Obviously I could redesign my controllers and make them more transparent. But this is not the point right now.

So lets look at our controller:



/**
* should be a service and not a method in the controller, bad design from me. -5 points
*/
def exportStudies(def studies, def response, String format, String extension, String filename) {

//title of the file
def parameters = [title: "Study Design"]

//required labels and mappings
def label = [
"classId": "Class Id",
"comment": "Comment",
"fileName": "Filename",
"label": "Label",
"organName": "Organ",
"speciesName": "Species",
"treatment": "Treatment"
]

//required fields
def fields = [
"classId",
"comment",
"fileName",
"label",
"organName",
"speciesName",
"treatment"
]
//contains out data for the save
def data = []

studies.each {Studie studie ->

//fill our object with data
studie.classes.each {BaseClass clazz ->
if (clazz instanceof ExperimentClass) {
clazz.samples.each {Sample sample ->

StudieExportObject exportObject = new StudieExportObject()

exportObject.classId = clazz.id
exportObject.speciesName = clazz.species.name
exportObject.organName = clazz.organ.name
exportObject.treatment = clazz.treatmentSpecific.toParentString()
exportObject.fileName = "${sample.fileName}_${sample.fileVersion}"
exportObject.comment = sample.comment
exportObject.label = sample.label

data.add(exportObject)

}
}
}
}

//set the extension to xls
response.setHeader("Content-disposition", "attachment; filename=${filename}.${extension}")

//calling the export service, which is really uggly implemented
exportService.export(format, response.outputStream, data, fields, label, [:], parameters)

}

/**
* export the studie as xls file
*/
def exportStudieToXLS = {

Studie studie = Studie.get(params.id)

if (studie == null) {
flash.message = "sorry this object wasn't found!"
redirect(action: "list", controller: "studie")
}
else if (!studie.canAccess()) {
flash.message = "sorry you do not have the permission to access this object!"
redirect(action: "list", controller: "studie")
}
else {

//run the export
exportStudies([studie], response, "excel", "xls", studie.id.toString())
}
}



after spending some time with the attempt to setup the export service correctly, I just scrapped this approach and figured. I assume it works and it's well tested. So lets rather test our logic and make sure it works. Hence we just mock the service in our test.


void testExportStudies() {


Studie studie = AquisitionTableServiceTests.generateNamedStudie(20, false)

GCTof tof = GCTof.list()[0]

AquisitionTableService service = new AquisitionTableService()
GenerateFileNameService generateFileNameService = new GenerateFileNameService()
generateFileNameService.modifyClassService = new ModifyClassService()

generateFileNameService.addCalibrationSamples(studie, tof, new Date(), ShiroUser.list()[0])
generateFileNameService.addReactionBlankSamples(studie, tof, new Date(), ShiroUser.list()[0])
generateFileNameService.addQualityControlSamples(studie, tof, new Date(), ShiroUser.list()[0])


ExportStudieController controller = new ExportStudieController()

//mocking the export service, since the developer of it did a really shitty job to ensure it can be easily tested, FAIL
controller.exportService = [
export : { def a, def b, def c, def d, def e,def f, def g ->
assertTrue(a instanceof String)
assertTrue(b instanceof OutputStream)
assertTrue(c instanceof Collection)
assertTrue(d instanceof Collection)
assertTrue(e instanceof Map)
assertTrue(f instanceof Map)
assertTrue(g instanceof Map)

//some cool testing logic gets here...
}
] as ExportService

controller.metaDataService = new MetaDataService()

controller.exportStudies([studie], controller.response, "csv", "txt", "test")
}

No comments:

Post a Comment