Unit testing: testing controller using Testing Plugin

 

by Taras Matyashovsky

 

In previous posts (Unit testing: testing domain entity using Testing Plugin and Unit testing: testing service in 3 different ways (part III)) we covered how to write unit test for domain entity and for simple service using Grails Testing Plugin. In this post I would like to show You how to write a simple unit test for controller using special mock*() function and special unit test case - mockController() and ControllerUnitTestCase. Suppose that we have simple User controller. In our example we will test update_account_information method. Let's have a look in details:

 

class UserController {

 

    // Controller uses user service

    // by dynamic injection.

    def userService

 

    def update_account_information = {

        User user = userService.retrieveUserById(

            session.user.id)

        user.email = params.email

        user.firstName = params.firstName

        user.lastName = params.lastName

 

        try {

            userService.saveUser(user)

 

            render(view: "profile", 

                model: [user: user, 

                    accountInformationUpdateMessageCode:

                "User.account.information.updated"

                ])

        }

        catch (InvalidUserException e) {

            render(view: "profile", 

                model: [user: user])

        }

    }

 

    // Some other methods.

 

}

 

 

As You can see - nothing complicated. Let's create a simple unit test using Grails Testing Plugin:

 

class UserControllerTests extends ControllerUnitTestCase {

 

    def controller

 

    UserControllerTests() {

        // Will test User controller class.

        // Do not forget to call super method at first.

        // It will create test for specific controller.

        super(UserController)

    }

 

    void setUp() {

        // Do not forget to call super method at first.

        super.setUp()

 

        // You have to initialize controller manually,

        // There is no dynamic injection.

        controller = new UserController()

 

        // Initialise the user service.

        def userService = new UserService()

 

        controller.userService = userService

    }

 

    void testUpdateAccountInformationSuccess() {

        // Mocking domain classes.

        def user = new User(id: 1L, 

            email: " This e-mail address is being protected from spambots. You need JavaScript enabled to view it ", 

            firstName: "Taras", lastName: "Matyashovsky", 

            password: "some hash")

        mockDomain(User, [user])

 

        // Putting user into session.

        controller.session.user = user

 

        // Setting controller's parameters.

        controller.params.email = 

            " This e-mail address is being protected from spambots. You need JavaScript enabled to view it "

        controller.params.firstName = "Tarasuk"

        controller.params.lastName = "Matyash"

 

        // Testing the target method.

        controller.update_account_information()

 

        // Assertions.

        assertEquals "profile", renderArgs.view

        assertEquals user, renderArgs.model.user

        assertEquals "User.account.information.updated",

renderArgs.model.accountInformationUpdateMessageCode

    }

 

    void testUpdateAccountInformationFailure() {

        // Mocking domain classes.

        def user = new User(id: 1L, 

            email: " This e-mail address is being protected from spambots. You need JavaScript enabled to view it ", 

            firstName: "Taras", 

           lastName: "Matyashovsky")

        mockDomain(User, [user])

 

        // Putting user into session.

        controller.session.user = user

 

        // Passing invalid parameters.

        controller.params.email = "INVALID EMAIL ADDRESS"

        controller.params.firstName = "Tarasuk"

        controller.params.lastName = "Matyash"

 

        // Testing the target method.

        controller.update_account_information()

 

        assertEquals "profile", renderArgs.view

        assertEquals user, renderArgs.model.user

    }

 

}

 

 

Pay attention to few key points:

 

  • by using ControllerUnitTestCase the controller's render method and params property work without any work on our part. This is true of all the dynamic properties and methods of the controller: request, response, params, session, controllerName, redirect, etc. All stuff is done by Testing Plugin
  • do not forget to call super methods - this will make sure that test will mock appropriate controller class

 

That's all for now. 

 
 
 

Add comment


Security code
Refresh