For instance, we have simple Document domain class:
And let's create a simple Document service for handing save and retrieve operations: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}]"""
}
}
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
   }
}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())
       }
    }
}- Not all dynamic methods can be mocked using metaClass property.
- 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.
 
 
No comments:
Post a Comment