Question

I am doing Grails tutorials on IBM(here) but I am a quite disappointed by an integration test. To sum up : I call a method who render a JSON object according to the ID (iata).

My domain is :

 class Airport {        
    String name
    String iata
}

My controller is :

class AirportController {

    // In order to enable scaffolding
    def scaffold = Airport

    def iata = {
        def iata = params.id?.toUpperCase() ?: "NO IATA"
        def airport = Airport.findByIata(iata)
        if (!airport) {
            airport = new Airport(iata: iata, name: "Not found")
        }

        render airport as JSON
    }    
}

When I do : http://localhost:8080/trip-planner/airport/iata/foo (in order to retreive null value) or http://localhost:8080/trip-planner/airport/iata/DEN (for DENVER), the method works fine !

The issue is my Integration tests :

class AirportControllerTests extends GroovyTestCase {
    void testWithGoodIata(){
        def controller = new AirportController()
        controller.metaClass.getParams = { ->
        return ["id":"den"]
        }

        controller.iata()

        def response = controller.response.contentAsString
        assertTrue response.contains("Denver")
    }

    void testWithWrongIata() {
        def controller = new AirportController()
        controller.metaClass.getParams = { ->
        return ["id":"foo"]
        }

        controller.iata()

        def response = controller.response.contentAsString
        assertTrue response.contains("\"name\":\"Not found\"")      
    }
}

The problem is:

Whenever I run the tests (by running : grails test-app -integration trip.planner.AirportControllerTests), I will always obtain a good behavior in the first test and a groovy.lang.MissingMethodException in the second test. (even if I switch the two : the second test always fail)

If I run them separately , it works. The exception occurred at this line (in the controller) : def airport = Airport.findByIata(iata)

Is that someting to do with "transactional" ? Any help would be great :)

P.S : I am using Grails 2.2.1

The exception stacktrace :

groovy.lang.MissingMethodException: No signature of method: trip.planner.Airport.methodMissing() is applicable for argument types: () values: []
    at trip.planner.AirportController$_closure4.doCall(AirportController.groovy:39)
    at trip.planner.AirportControllerTests.testWithWrongIata(AirportControllerTests.groovy:25)
Was it helpful?

Solution

I suspect the metaclass changes you're making in one test are somehow leaking through to the other. But you don't need to (and shouldn't) manipulate the metaclass in an integration test, just say

def controller = new AirportController()
controller.params.id = "den"

You only need to do mocking for unit tests.

Bear in mind that the tutorial you're looking at was written way back in 2008 (in the Grails 1.0.x days), and Grails has moved on a very long way since then, with some components (including testing) having been through one or more complete rewrites.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top