Grails Unit Testing and a little fun with @Before

So, we’ve been using Grails at gibbon’s five for a while now and stumbled into different problems with our unit tests. One of the weirdest ones were occasionally failing tests on our Jenkins that never failed locally. So we digged into this a little and came up with a simple explanation, that I’d like to share with you.

Let’s assume we have a controller and want to test it. First thing you’d probably do is go to the Grails Guide, Chapter 10: Unit Testing Controllers and start with something like this:

import grails.test.mixin.TestFor

@TestFor(SimpleController)
class SimpleControllerTests {
    void testSomething() {
    }
}

Now, if you have multiple tests which need some variable set inside the (controller.)request and you have a little knowledge of JUnit, you’d probably come up with something like this:

import grails.test.mixin.TestFor
import org.junit.Before

@TestFor(SimpleController)
class SimpleControllerTests {
    @Before
    void initialize() {
        request.variable = "foobar"
    }
    void testSomething() {
        // some code here needs the request.variable
    }
    void testSomethingElse() {
        // some code here needs the request.variable
    }
}

This is bad.

Continue reading “Grails Unit Testing and a little fun with @Before” »

Grails with time-based rolling logs

Logging in grails is somehow confusing me a little. I don’t know why but even though I’m familiar with log4j and never had trouble working with it, grails logging sometimes manages to make me feel like a total newbie. After looking for a nice and simple solution for a timebased rolling and archiving, I thought someone else might be interested in it as well and I don’t have to look for it again ;) So here is the daily rolling log configuration, which is also archiving (and zipping) the old log:
Continue reading “Grails with time-based rolling logs” »

Ajax Upload tweaked for grails

While coding a little on gibbon’s five we stumbled upon a nice JavaScript library called file uploader. The first tests we did looked good so we took it into the project. While checking the browser compability I ran into some problems with the Internet Explorer that need to be fixed.

First of all, the return type for the IE has to be a little different – the IE needs text/plain. Also, the data send from the IE to the server looks a little different from the one WebKit and gecko: It’s a CommonsMultipartFile. Therefore I had to do some tweaking on the server side which ended in some code pretty similar to this:

if (params.qqfile instanceof org.springframework.web.multipart.commons.CommonsMultipartFile){
    returnType = 'text/plain'
    content = params.qqfile.getInputStream()
    originalFilename = params.qqfile.originalFilename
    mimeType = params.qqfile.getContentType()
} else {
    returnType = 'application/json'
    content = request.inputStream
    originalFilename = params.qqfile
    mimeType = URLConnection.guessContentTypeFromName(params.qqfile)
}

Furthermore, the plugin has to deal with older browsers and the IE by using iframes (mentioned on the website and explained in the code). This works pretty well until you come across grails, which, for whatever reason, sends pre-tags around the json code. Of course our friend the Internet Explorer is confused and is simply not evaluating the answer. A simple solution to this is to change a few lines of code in the function (fileuploader.js):

_getIframeContentJSON:function (iframe) {
    // iframe.contentWindow.document - for IE<7
    var doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document, response;

    this.log("converting iframe's innerHTML to JSON");
    this.log("innerHTML = " + doc.body.innerHTML);

    // Grails is answering with pre-tags. That might confuse the browser script therefore we better remove them.
    var cleanedAnswer = doc.body.innerHTML.replace(/<(\/)*pre>/g, '');
    this.log("grails cleaned: " + cleanedAnswer);

    try {
        response = eval("(" + cleanedAnswer + ")");
    } catch (err) {
        response = {};
    }

    return response;
}

Overall it’s a simple tweak and now it works perfectly within all the browsers we tried :)