Sunday, February 8, 2009

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.

No comments:

Post a Comment