Wednesday, February 18, 2009

Grails: reading configuration at runtime

As far as You know some basic configuration in Your Grails application is located in Config.groovy (under grails-app/conf folder). Often it is very useful to access data from it at runtime. To do that You have to use org.codehaus.groovy.grails.commons.ConfigurationHolder. For example, let's read SMTP properties from one of the previous posts.

Config.groovy:
// Some simple SMTP configuration.
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "youracount@gmail.com"
password = "yourpassword"
props = ["mail.smtp.auth":"true"]
}
}

Some service, for instance Email service:
// Using import aliasing.
import org.codehaus.groovy.grails.commons.ConfigurationHolder
as confHolder

class EmailService {

def sendEmail() {
// Reading property by name.
def username = confHolder.config.grails.mail.username
}

}

As You can see its very simple. In order to have access to Grails configuration from controllers or tags use grailsApplication: in our case grailsApplication.config.grails.mail.username. Enjoy!

Groovy import aliasing

One of the Groovy features I've discovered recently is "import aliasing". For instance, You have two classes with the same name located in two different packages. When You would like to use them together there will be conflict and to resolve it You have to use one of the mentioned classed with full package name. If someone faced such situation You know how inconvenient it is. Groovy helps to solve such situation using "import aliasing": there is an opportunity to set an alias for every import in Your class. For instance, You want to use two different Calendar classes. Let's create alias for own Calendar entity:

package com.mycompany.myorganization.core.service

import java.util.Calendar
import com.mycompany.myorganization.core.domain.Calendar
as MyCalendar

// Some other imports.

class UserService {
// Using both Calendars.
// Exampe of using own Calendar entity:
// MyCalendar myCalendar = new MyCalendar()

}

Another situation when You can use aliasing is long package names.
That's all. Enjoy it!

Monday, February 16, 2009

Unit testing: testing controller using Testing Plugin

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: "taras.matyashovsky@gmail.com",
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 =
"taras.matyashovsky@gmail.com"
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: "taras.matyashovsky@gmail.com",
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.

Sunday, February 15, 2009

Grails Integration Testing: common information

Integration tests differ from unit tests in that you have full access to the Grails environment within the test. Grails will use an in-memory HSQLDB database (or another configured data source, for instance MySQL) for integration tests and clear out all the data from the database in between each test. You have to understand that each test is wrapped into transaction which will be rolled back lately. So integration test:
  • will talk to database, so it will be slower than unit test
  • will persist data to database - make sure Your test environment database setting don't point to production or development database
A couple of helpful thoughts concerning integration tests:
  1. You have to initialize the service class yourself, there is no dynamic injection. It is the same way as it was during unit testing.
  2. If the service has other service class inside it, You have to initialize and assign it manually. Also it is the same way as it was during unit testing.
  3. Sometimes it is useful to flush session in order to persist to database immediately - else You might get weird thing like no "id" for the supposedly saved domain object or deleted objects would be not deleted. How to do that? It's very easy, please look at the simple example:
    class DocumentServiceTests extends GroovyTestCase {

    def documentService

    // Dynamic injection of session factory.
    def sessionFactory

    void setUp() {

    // You have to initialize service,
    // there is no dynamic injection.

    documentService = new DocumentService()
    }

    void testSomething() {

    // Some logic. For instance,
    // documentService.deleteDocumentById(1L).
    // But document is still not
    // deleted after execution.
    // You have to manually flush the session
    // before assertions.

    sessionFactory.currentSession.flush()
    sessionFactory.currentSession.clear()

    // Assertions.
    }

    }


That's all for now.

Wednesday, February 11, 2009

Grails Mail plugin usage

Essential feature of every web application is possibility to send emails. Traditionally when You will look through Grails reference You will find page concerning proposals for email integration in Grails. But approaches mentioned there are not perfect and their implementation in our application was quiet hard. So I decided to look for another solutions and found excellent Grails Mail Plugin. You can easily install it using command:
grails install-plugin mail

Grails Mail Plugin integration is very simple - everything You need is to dynamically inject mail service into Your service. After that You can use its sendMail method for sending email:
class MyService {

// Dynamic injection happens here.
MailService mailService

def someMethod() {
// Some logic.
mailService.sendMail {
to "email@mail.com"
from "youraccount@gmail.com"
subject "Test mail"
html """Hello!
This is a test email. """
}
}
}
Do not forget to configure Your mail server, configuration is located in grails-app/Config.groovy file. In my example it can be similar to listed below:
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "youraccount@gmail.com"
password = "yourpassword"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}

One topis is not covered - unit and integration testing of mail service. You will not believe but only thing You need is to initialise mail service in Your integration or unit test and connent it to my service. Short example:
class MyServiceTests extends GrailsUnitTestCase {

MyService myService

void setUp() {
// Do not forget to call super method at first.
super.setUp()

// Initialize the my service.
userService = new UserService()
// Initialize the mail service and
// connect it to my service

userService.mailService = new MailService()
}

// Some tests.

}
That's all concerning Grails Mail Plugin, hope You enjoyed it.

Tuesday, February 10, 2009

Grails combining integration and unit testing

Yesterday I faced the situation when in integration test I needed some logic to be mocked and to be executed in particular way. Therefore I asked a question about possibility of combining integration and unit testing approaches. In someone is interested - please review mentioned situation in details. Do not forget that is based on Grails Testing Plugin, so if You are new to it please review some of my previous posts.

I have FileService which has methods for saving/retrieving/deleting files in local file system. Files are distinguished by guid, and full path to the file is generated using storage root property plus mentioned guid. Storage root property is hard coded into the service (I know that is not the best solution but quiet comfortable for me). Described logic is listed below:
class FileService {

// File system's storage root. Hardcoded.
String storageRoot = "C:\\"

def retrieveFullPath(String guid) {
"${storageRoot}\\${guid}.pdf"
}

// Some other methods for
// saving/retrieving/deleting files.


}

Also I have other service called Project Service in which File Service is dynamically injected using Spring. It uses its retrieveFullPath method. Let's look more concrete:
class ProjectService {

def fileService

def retrieveProject(String guid) {
// Some logic.
def filePath = fileService.retrieveFullPath(guid)
// Some logic.
}

// Some other methods.
}

Everything looking good and I decided to write simple integration test. But faced with the first question: in my test I need test file to be stored somewhere in the test folder of the application. But when I will use it's guid, file service will retrieve full path according to storage root property and that path will be invalid and exception will be thrown. Therefore I decided to mock mentioned logic in order to retrieve real file which exists under test folder. Let's have a look at the test:

class ProjectServiceTests extends GrailsUnitTestCase {

def projectService

void setUp() {
// Do not forget to call super method at first.
super.setUp()

// Initialise the service.
// There is no dynamic injection.

projectService = new ProjectService()
}

void testRetrieveProject() {
// Loading file for test folder
// using Spring's ClassPathResource class.

def fileName =
new ClassPathResource("test/testfile.pdf")
.getFile().getPath()


// Mocking file service not to use its storage root
// and to return needed file path.
// In this case file service will return
// real path to the file in Your file system.

def fileServiceMock = mockFor(FileService)
fileServiceMock.demand.retrieveFullPath {
String guid ->
return fileName
}

// Creating a file service mock
// in project service.

projectService.fileService =
(FileService) fileServiceMock.createMock()

// Calling the target method.
projectService.retrieveProject("testfile")

// Some assertions.
}

}

That's all. In listed integration test we combined some approaches from unit testing. Hope someone found it interesting.

Grails Testing Plugin often occurred exception

In previous posts (service unit testing and domain entity unit testing) I told You a lot about Grails Testing Plugin, its simple usage, but have not paid necessary accent on one often occurred exception:
"Cannot invoke method containsKey() on null object" type="java.lang.NullPointerException"

It happens then You override setUp() method but forget to call super method at first. So instead of writing:
class SomeTests extends GrailsUnitTestCase {

void setUp() {
// Some initializations.
}

}

Call super method at first:
class SomeTests extends GrailsUnitTestCase {

void setUp() {

// Call super method at first.

super.setUp()


// Some initializations.

}

}

That's all.

Monday, February 9, 2009

GORM 1 to 0..1 relationship issue

Recently I wanted to create one-to-one relationship (1 to 0..1) not pure 1 to 1. But unfortunately faced with the problem. Let's review it in details (entity A can have association with zero or only one entity B):
class A {
B b

static constraints = {
b(nullable: true)
}

}

class B {
A a

static belongsTo = [A]
}

Grails generated the database schema in such way: table A has column b_id (as it has to be), but it cannot be nullable. As You can see for 1 to 0..1 relationship this is a wrong behavior. I posted question on Nabble forums (as I recommended to everyone:) ) and received answer that mentioned problem will be fixed in Grails 1.1. For more details visit appropriate forum post.

Grails code coverage plugin issue

Recently I've installed official Grails Code Coverage plugin (called Cobertura). As fas as I'm using Grails 1.0.4 appropriate code coverage plugin version for me is 0.9. You also can install it using simple Grails command:
grails install-plugin code-coverage 0.9
But when I tried to use it and to generate test reports using command:
grails test-app-cobertura
I've got an exception:
[cobertura-report] java.lang.NoClassDefFoundError: org/apache/log4j/Category
[cobertura-report] Exception in thread "main"
Reason for that was that Code Coverage plugin needs log4j library to be present in project library folder. So when I downloaded latest version (for me it was 1.2.15) everything worked great. Enjoy using Grails Code Coverage Plugin!

Sunday, February 8, 2009

Unit testing: testing domain entity using Testing Plugin

In previous post we got acquainted with Grails Testing Plugin. In this post we will look closer how to write unit test for domain class, especially how to easily test its constraints. As far as I mentioned Testing Plugin includes a lot of mock*() methods for testing domain entities, controllers, tag libs, etc. One of such methods is mockForConstraintsTests() method which is very useful to check whether the constraints are behaving as you expect them to.
Suppose we have a simple domain class like so:

class User {

String email
String firstName
String lastName
String password

static constraints = {
email(email: true, unique: true, blank: false,
maxSize: 64)
firstName(blank: false, minSize: 2, maxSize: 32)
lastName(blank: false, minSize: 2, maxSize: 32)
password(blank: false, maxSize: 128)
}

String toString() {
"""User [email: ${email},
firstName: ${firstName},
lastName: ${lastName}]"""
}

}


To test these constraints we can do the following:

class UserTests extends GrailsUnitTestCase {

void testUserConstraints() {

// Assume that we have an existing user
// in the database.

def existingUser = new User(
email: "taras.matyashovsky@gmail.com",
firstName: "Taras",
lastName: "Matyashovsky",
password: "some hash")
// Using mockForConstraintsTests for mocking.
mockForConstraintsTests(User, [existingUser])


// Validation should fail if email or
// first name or last name or
// password properties are null.

def user = new User()
assert !user.validate()
assertEquals "nullable", user.errors["email"]
assertEquals "nullable", user.errors["firstName"]
assertEquals "nullable", user.errors["firstName"]
assertEquals "nullable", user.errors["password"]


// So let's demonstrate the unique
// and min size constraints.
// Insert user with the same email
// and very short first and last names.

user = new User(
email: "taras.matyashovsky@gmail.com",
firstName: "T",
lastName: "M",
password: "some hash")
assert !user.validate()
assertEquals "unique", user.errors["email"]
assertEquals "minSize", user.errors["firstName"]
assertEquals "minSize", user.errors["lastName"]


// So let's demonstrate the max size constraints.
// First name is too long (more than 32 symbols).

user = new User(
email: "grails-groovy@blogger.com",
firstName: "TarasTarasTarasTarasTarasTarasTaras",
lastName: "Matyashovsky",
password: "some hash")
assert !user.validate()
assertEquals "maxSize", user.errors["firstName"]


// Validation should pass.

user = new User(
email: "andriy.suran@gmail.com",
firstName: "Andriy",
lastName: "Suran",
password: "some hash")
assert user.validate()
}

}


Using errors property we can access all the properties and methods we should normally expect. We simply specify the name of the field we are interested in and the map/property access will return the name of the constraint that was violated. Testing Plugin makes testing easy.

Unit testing: testing service in 3 different ways (part III)

In previous posts (part I and part II) we tested simple service using ExpandoMetaClass and Groovy Mocks. In this post we will test simple service using new Grails Testing Plugin, which will be included into Grails 1.1. The Testing Plugin targets weaknesses of mentioned approaches by providing a set of classes that make testing many of Grails' artifacts really easy, while providing plenty of flexibility. For installation details visit official Testing Plugin page. Main features:
  1. The core of the testing plugin is the grails.test.GrailsUnitTestCase class. So each test should extend this class instead of groovys.util.GroovyTestCase.
  2. Special mock*() methods. Using these methods ensures that any changes you make to the given classes do not leak into other tests. It also includes special mock*() methods for mocking domain objects, controllers, for testing constraints, tag libs, etc.
Lets rewrite simple test from previous posts using the Testing Plugin.

class DocumentServiceTests extends GrailsUnitTestCase {

def documentService

void setUp() {

// Do not forget to call super setUp()
// otherwise tests will fail!.

super.setUp()


// Initialize the service class,
// there is no dynamic injection.

documentService = new DocumentService()
}

void testSaveDocumentSuccess() {

// Mock the domain class.
// Using mockDomain method.

def testInstances = []
mockDomain(Document, testInstances)


// Testing the target method.
// Testing not differs
// from "real" service method call.

documentService.saveDocument(
new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: new User()))
}

void testSaveDocumentFailure() {

// Mock the domain class.
// Using mockDomain method.

def testInstances = []
mockDomain(Document, testInstances)

shouldFail(InvalidDocumentException) {

// Validation will fail.

documentService.saveDocument(
new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L))
}
}

void testRetrieveDocumentByIdAndOwnerSuccess() {
def owner = new User()


// Mock the domain class.
// Using mockDomain method.

def testInstances = [new Document(
id: 1L,
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: owner)]
mockDomain(Document, testInstances)


// Testing the target method.
// Testing not differs
// from "real" service method call.

def foundDocument =
documentService.retrieveDocumentByIdAndOwner(
1L, owner)

// Assertions.
assertNotNull foundDocument
assert "Document name" == foundDocument.name
assert "Document description" == foundDocument.description
assert 1 == foundDocument.revisionCount
}

void testRetrieveDocumentFailure() {

// Mock the domain class.
// Using mockDomain method.

def testInstances = []
mockDomain(Document, testInstances)

shouldFail(DocumentNotFoundException) {

// Method will fail as there are
// no test instances to be retrieved.

documentService.retrieveDocumentByIdAndOwner(
1L, new User())
}
}

}

As You can see Testing Plugin makes unit testing quiet easy. In this post we covered only basic features, if someone will be interested we will look closer into other special features. I recommend to use mentioned plugin instead of using ExpandoMetaClass and Groovy Mocks.

Saturday, February 7, 2009

Unit testing: testing service in 3 different ways (part II)

In part I we got acquainted with unit testing of services based on ExpandoMetaClass approach. In this part we will look on a method based on Groovy Mocks. Groovy has excellent built-in support for a range of mocking alternatives. Let's rewrite test from the previous post in order to use Groovy Mocks.

class DocumentServiceTests extends GroovyTestCase {

def documentService

void setUp() {

// Initialize the service class,
// there is no dynamic injection.

documentService = new DocumentService()
}

void testSaveDocumentSuccess() {
// Create the Mock support
// for Document class.

def documentMocker = new MockFor(Document)


// Demand the validate method exactly once,
// and programming it to return true.

documentMocker.demand.validate {
return true
}


// Demand the save method exactly once,
// and programming it to return true.

documentMocker.demand.save {
return true
}

// Start using the Mock.
documentMocker.use {
documentService.saveDocument(
new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: new User()))
}
}

void testSaveDocumentFailure() {

// Create the Mock support
// for Document class.

def documentMocker = new MockFor(Document)


// Demand the validate method exactly once,
// and programming it to return false.

documentMocker.demand.validate {
return false
}

// Start using the Mock.
documentMocker.use {
// Validation will fail.
// Expecting exception to be thrown.

shouldFail(InvalidDocumentException) {
documentService.saveDocument(
new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L))
}
}
}

void testRetrieveDocumentByIdAndOwnerSuccess() {

// Create the Mock support
// for Document class.

def documentMocker = new MockFor(Document)


// Demand the findByIdAndOwner method exactly once,
// and programming it to return appropriate document.

documentMocker.demand.findByIdAndOwner {
Long id, User owner ->
return new Document(
id: id,
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: owner)
}


// Demand the getName method exactly once,
// and programming it to return appropriate name.
// Needed for assertion.

documentMocker.demand.getName {
return "Document name"
}


// Demand the getDescription method exactly once,
// and programming it to return appropriate name.
// Needed for assertion.

documentMocker.demand.getDescription {
return "Document description"
}


// Demand the getRevisionCount method exactly once,
// and programming it to return appropriate name.
// Needed for assertion.

documentMocker.demand.getRevisionCount {
return 1L
}

// Start using the Mock.
documentMocker.use {
def foundDocument =
documentService.retrieveDocumentByIdAndOwner(
1L, new User())

assertNotNull foundDocument
assert "Document name" == foundDocument.name
assert "Document description" == foundDocument.description
assert 1 == foundDocument.revisionCount
}
}

void testRetrieveDocumentFailure() {

// Create the Mock support
// for Document class.

def documentMocker = new MockFor(Document)


// Demand the findByIdAndOwner method exactly once,
// and programming it to return NULL.

documentMocker.demand.findByIdAndOwner { Long id, User owner ->
return null
}

// Start using the Mock.
documentMocker.use {
// Document will not be found.
// Exception will be thrown.

shouldFail(DocumentNotFoundException) {
documentService.retrieveDocumentByIdAndOwner(
1L, new User())
}
}
}

}

Groovy Mocks have a lot of powerful features, especially You can mock few calls of service method, You can mock not only a tested service but also an injected service, etc. For more detailed information check resources listed below:
  1. Using MockFor and StubFor
  2. Mocking Static Methods using Groovy
In the next post we will rewrite mentioned test using Testing plugin.

GORM executeQuery nuance

As far as You know executeQuery method allows the execution of HQL queries against a domain class. In previous post I mentioned issue concerning it in Grails. To recall I will list the latest query using Groovy shortcuts once more:
DocumentRevision.executeQuery("select max(dr.versionNumber) from ${DocumentRevision.name} dr")
Now I want to mention one nuance more. In my query I suppose that result type would be a numeric cause versionNumber property is Long type. But result type of using executeQuery method is always java.util.ArrayList. So even if You try to retrieve maximal value of some field, or count of some records the result type will always be ArrayList. Pay attention to that fact.

If You are not satisfied with such behavior of executeQuery method please refer to createCriteria method.

GORM executeQuery problem

As far as You know executeQuery method allows the execution of HQL queries against a domain class. I never tried it before cause used dynamic finders instead. But when I first tried to execute simple HQL query:
DocumentRevision.executeQuery("select max(dr.versionNumber) from DocumentRevision dr")
I've got an exception:
Caused by: org.hibernate.hql.ast.QuerySyntaxException: DocumentRevision is not mapped.
That was quiet surprised for me cause DocumentRevision domain class is mapped and I could perform all CRUD operations with it.

Reason for that exception was
there is one somewhat frustrating difference between GORM and Hibernate default behaviors. By default in Hibernate the short class name is used and as long as the domain short class name is unique then this is fine. So in my case I should include DocumentRevision with whole package name:
DocumentRevision.executeQuery("select max(dr.versionNumber) from com.myorg.myproject.core.domain.DocumentRevision dr")
But the easiest way I discovered of to work around this is to use a couple of Groovy shortcuts:
DocumentRevision.executeQuery("select max(dr.versionNumber) from ${DocumentRevision.name} dr")
"$DocumentRevision.name" is the equivalent of "DocumentRevision.class.getName()". It's not much longer than what I originally tried, so I stopped research on mentioned solution.

Grails clean command

Many times I faced the situation when Grails application has been screwed and comes up with mysterious error messages. Particularly Grails can create columns in database for the fields that were removed from the domain entity long time ago, services perform logic that also was removed long tome ago, etc. In that case try to execute command:
grails clean
If its still not working properly after that the last option is to clean IntelliJ IDEA cache.

Unit testing: testing service in 3 different ways (part I)

Let's start with simple unit testing. If someone will be interested I could improve it with more complicated features. In part I we will use ExpandoMetaClass approach for unit testing.

For instance, we have simple Document domain class:

class Document {
String name
String description
Date creationTime
Date lastModifiedTime
Long revisionCount
User owner

static constraints = {
name(blank: false, maxSize: 64)
description(nullable: true, maxSize: 1024)
}

static belongsTo = [User]

String toString() {
"""Document [name: ${name},
description: ${description},
lastModifiedTime: ${lastModifiedTime}]"""
}

}
And let's create a simple Document service for handing save and retrieve operations:
class DocumentService {

def saveDocument(Document document)
throws InvalidDocumentException {
if (document.validate()) {
document.save()
} else {
throw new InvalidDocumentException(
document: document)
}
}

def retrieveDocumentByIdAndOwner(Long id, User owner)
throws DocumentNotFoundException {
Document document = Document.findByIdAndOwner(id, owner)
if (!document) {
throw new DocumentNotFoundException([id: id,
owner: owner].toMapString())
}

document
}

}
Lets create simple unit test for listed service using ExpandoMetaClass approach. As far as You remember during unit tests Grails does not inject any of the dynamic methods present during integration tests and at runtime. So we have to mock them in our tests.
class DocumentServiceTests extends GroovyTestCase {

def documentService

void setUp() {

// We have to initialize service class,
// there is no dependency injection.

documentService = new DocumentService()
}

void testSaveDocumentSuccess() {
def documentToSave = new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: new User())


// Dynamically add (mock) method validate to all
// instances of Document class and
// suppose it always return true.

Document.metaClass.static.validate = {
return true
}


// Dynamically add (mock) method save to all
// instances of Document class and
// suppose it always return true.

Document.metaClass.static.save = {
return true
}


// Saving will pass cause validate and
// save methods will return true.

documentService.saveDocument(documentToSave)
}

void testSaveDocumentFailure() {
def documentToSave = new Document(
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L)


// Dynamically add (mock) method validate to all
// instances of Document class and
// suppose it always return false.

Document.metaClass.static.validate = {
return false
}


// Saving will fail cause validation will fail.

shouldFail(InvalidDocumentException) {
documentService.saveDocument(documentToSave)
}
}

void testRetrieveDocumentByIdAndOwnerSuccess() {

// Mock dynamic finder method to all
// instances of Document class and
// suppose it always return some document.

Document.metaClass.static.findByIdAndOwner = {
Long id, User owner ->
return new Document(id: id,
name: "Document name",
description: "Document description",
lastModifiedTime: new Date(),
creationTime: new Date(),
revisionCount: 1L,
owner: owner)
}

// Test the target method,
// it will return supposed document.

def foundDocument = documentService.retrieveDocumentByIdAndOwner(
1L, new User())

assertNotNull foundDocument
assert "Document name" == foundDocument.name
assert "Document description" == foundDocument.description
assert 1 == foundDocument.revisionCount
}

void testRetrieveDocumentByIdAndOwnerFailure() {

// Mock dynamic finder method to
// all instances of Document class and
// suppose it always return NULL.

Document.metaClass.static.findByIdAndOwner = {
Long id, User owner ->
return null
}


// Test the target method, it will fail cause
// no document instance will be found.

shouldFail(DocumentNotFoundException) {
documentService.retrieveDocumentByIdAndOwner(
1L, new User())
}
}

}
As You can see using ExpandoMetaClass is quiet easy. But be aware of using such approach cause some nuances are present:
  1. Not all dynamic methods can be mocked using metaClass property.
  2. Mocks using ExpandoMetaClass are created for whole tests (including integration tests). So if You mock some method for particular class in some unit test it will affect execution of mentioned method for particular class in other tests, so result can be unpredictable.

Testing in Grails: common information

Grails supports the concepts of:
  1. Unit testing - testing individual methods or blocks of code without considering for surrounding infrastructure. You have to mock these methods or blocks using something like Groovy Mock or ExpandoMetaClass. Alternatively, you could using the Testing plugin. I will show all 3 approaches in future posts.
  2. Integration testing - you have full access to the Grails environment within the test. Grails will use a database (HSQLDB, MySQL or another found in Grails configuration) for integration tests and clear out all the data from the database in between each test.
  3. Functional testing - involve testing the actual running application. Grails has support for functional testing via Canoo WebTest plug-in.
Also be aware that You have to test all layers of the application:
  1. Domain entities - usually You have to write unit tests for validation process.
  2. Services - usually You have to write unit and integration tests to be sure that services are working properly.
  3. Controllers - usually You have to write unit and integration tests to be sure that controllers are working properly.
We will cover all mentioned tests on real examples for all layers in future posts.

Useful books and resources concerning Groovy/Grails

When I just started with Groovy/Grails I faced the problem of finding good books/blogs/resources. Therefore I want to share some useful links for the beginners:
  1. I recommend Appress books concerning Groovy/Grails especially Beginning Groovy.
  2. Grails reference is quiet laconic but useful in any time.
  3. If You have any problems or need qualified support I recommend Nabble forums, there are a lot of posts concerning Groovy/Grails problems.
  4. Blogs on www.blospot.com
This post will be updated frequently cause I will try to ind more useful resources.

Importing Grails project into IntelliJ IDEA

I prefer IntelliJ IDEA as my Integrated Development Environment (IDE). Currect IDEA version is 8.0.*.
After You've created Your Grails project using
grails create-app application_name
please follow few simple steps to import newly created project to IntelliJ IDEA:
  1. Check that file application_name/.project is created. This is the Eclipse project file generated by grails create-app command during the initial project creation. IntelliJ IDEA is capable of opening such files and transforming them into IntelliJ IDEA project files.
  2. Start IntellIJ IDEA, click File > Open Project ... menu item and specify .project file as target. IntelliJ IDEA will process the file and will create project, module and workspace files.
  3. Next you need to tell IntelliJ IDEA to enable Grails support. It may be achieved by registering Grails facet for the project. Intellij IDEA may detect the facet itself and ask to register it. In case it will not, you have to do it manually.
  4. In order to manually register Grails facet open the context menu for your module item in project explorer and click on Module Settings. On the Project Structure window click + button and choose Grails facet. Then just apply the settings and close the window. Module icon will be updated with Grails facet icon - this will tell you that project module is Grails-ready.
  5. Before proceeding make sure that your project uses appropriate JDK. Click File > Project Structure and check the value in Project SDK combobox.
  6. Click Build > Rebuild Project to compile the sources - this step should be successfull, otherwise there is a trouble with your setup or source code base is broken.

First post

Hello everyone,

I'm Java developer who moved to Groovy/Grails recently.
In my blog I will post common simple issues and their solution concerning using Groovy and Grails. I hope that someone will find my posts useful and save time solving common problems.

Best regards.