Skip to content
Browse files

Changes to support fix for GRAILS-9637 "Grails Unit Tests using the n…

…ew Annotation framework is slow". Need verification of improvements.
  • Loading branch information...
1 parent 3e385a0 commit 6dfab1a5db4da8c176351f23d65c7fc0d4aa6364 @graemerocher graemerocher committed Feb 15, 2013
View
9 build.gradle
@@ -41,7 +41,7 @@ ext {
hibernateVersion = "3.6.10.Final"
ehcacheVersion = "2.4.6"
junitVersion = "4.10"
- concurrentlinkedhashmapVersion = "1.2_jdk5"
+ concurrentlinkedhashmapVersion = "1.3.1"
}
version = grailsVersion
@@ -79,15 +79,16 @@ if (jointBuildGroovyJarProperty) {
allprojects {
repositories {
+ mavenLocal()
maven { url "http://repo.grails.org/grails/core" }
}
configurations {
all {
resolutionStrategy {
- def cacheHours = isCiBuild ? 1 : 24
- cacheDynamicVersionsFor cacheHours, 'hours'
- cacheChangingModulesFor cacheHours, 'hours'
+// def cacheHours = isCiBuild ? 1 : 24
+// cacheDynamicVersionsFor cacheHours, 'hours'
+// cacheChangingModulesFor cacheHours, 'hours'
}
}
}
View
2 ...-bootstrap/src/main/groovy/org/codehaus/groovy/grails/resolve/GrailsCoreDependencies.java
@@ -134,7 +134,7 @@ public Object doCall() {
ModuleRevisionId.newInstance("org.grails", "grails-web", grailsVersion),
ModuleRevisionId.newInstance("org.slf4j", "slf4j-api", slf4jVersion),
ModuleRevisionId.newInstance("org.springframework", "spring-test", springVersion),
- ModuleRevisionId.newInstance("com.googlecode.concurrentlinkedhashmap", "concurrentlinkedhashmap-lru", "1.2_jdk5"),
+ ModuleRevisionId.newInstance("com.googlecode.concurrentlinkedhashmap", "concurrentlinkedhashmap-lru", "1.3.1"),
ModuleRevisionId.newInstance("junit", "junit", junitVersion),
};
registerDependencies(dependencyManager, "build", buildDependencies);
View
5 ...ss/src/main/groovy/org/codehaus/groovy/grails/domain/GrailsDomainClassMappingContext.java
@@ -121,5 +121,10 @@ public Set getOwningEntities(Class javaClass, MappingContext context) {
public IdentityMapping getIdentityMapping(ClassMapping classMapping) {
return null;
}
+
+ @Override
+ public void setCanExpandMappingContext(boolean canExpandMappingContext) {
+ // noop
+ }
}
}
View
7 .../src/main/groovy/org/codehaus/groovy/grails/domain/GrailsDomainClassPersistentEntity.java
@@ -50,6 +50,7 @@
private Map<String, PersistentProperty> propertiesByName = new HashMap<String, PersistentProperty>();
private List<PersistentProperty> properties = new ArrayList<PersistentProperty>();
private List<Association> associations = new ArrayList<Association>();
+ private boolean isInitialized;
public GrailsDomainClassPersistentEntity(GrailsDomainClass domainClass, GrailsDomainClassMappingContext mappingContext) {
this.domainClass = domainClass;
@@ -110,6 +111,12 @@ else if (grailsDomainClassProperty.isManyToMany()) {
associations.add((Association)persistentProperty);
}
}
+ isInitialized = true;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return isInitialized;
}
public String getName() {
View
94 ...s-plugin-testing/src/main/groovy/grails/test/mixin/domain/DomainClassUnitTestMixin.groovy
@@ -83,10 +83,11 @@ class DomainClassUnitTestMixin extends GrailsUnitTestMixin {
static void initializeDatastoreImplementation() {
ClassPropertyFetcher.clearCache()
if (applicationContext == null) {
- super.initGrailsApplication()
+ initGrailsApplication()
}
simpleDatastore = new SimpleMapDatastore(applicationContext)
+ simpleDatastore.mappingContext.setCanInitializeEntities(false)
transactionManager = new DatastoreTransactionManager(datastore: simpleDatastore)
applicationContext.addApplicationListener new DomainEventListener(simpleDatastore)
applicationContext.addApplicationListener new AutoTimestampEventListener(simpleDatastore)
@@ -118,6 +119,20 @@ class DomainClassUnitTestMixin extends GrailsUnitTestMixin {
simpleDatastore.clearData()
}
+ def mockDomains(Class... domainsClassToMock) {
+ initialMockDomainSetup()
+ for(Class c in domainsClassToMock) {
+ PersistentEntity entity = simpleDatastore.mappingContext.addPersistentEntity(c)
+ GrailsDomainClass domain = registerGrailsDomainClass(c)
+
+ Validator validator = registerDomainClassValidator(domain)
+ simpleDatastore.mappingContext.addEntityValidator(entity, validator)
+
+ }
+ def enhancer = new GormEnhancer(simpleDatastore, transactionManager)
+ enhancer.enhance()
+ simpleDatastore.mappingContext.initialize()
+ }
/**
* Mocks a domain class providing the equivalent GORM behavior but against an in-memory concurrent hash map instead
* of a database
@@ -126,17 +141,49 @@ class DomainClassUnitTestMixin extends GrailsUnitTestMixin {
* @return An instance of the mocked domain class
*/
def mockDomain(Class domainClassToMock, List domains = []) {
+ initialMockDomainSetup()
+ PersistentEntity entity = simpleDatastore.mappingContext.addPersistentEntity(domainClassToMock)
+ GrailsDomainClass domain = registerGrailsDomainClass(domainClassToMock)
+ simpleDatastore.mappingContext.initialize()
+// DomainClassGrailsPlugin.addRelationshipManagementMethods(domain, applicationContext)
+ Validator validator = registerDomainClassValidator(domain)
+ simpleDatastore.mappingContext.addEntityValidator(entity, validator)
+
+ enhanceSingleEntity(entity)
+ if (domains) {
+ saveDomainList(entity, domains)
+ }
+ else {
+ return applicationContext.getBean(domain.fullName)
+ }
+ }
+
+ protected void initialMockDomainSetup() {
ConstraintEvalUtils.clearDefaultConstraints()
grailsApplication.getArtefactHandler(DomainClassArtefactHandler.TYPE).setGrailsApplication(grailsApplication)
- GrailsDomainClass domain = grailsApplication.addArtefact(DomainClassArtefactHandler.TYPE, domainClassToMock)
- PersistentEntity entity = simpleDatastore.mappingContext.addPersistentEntity(domainClassToMock)
+ }
- final mc = GrailsClassUtils.getExpandoMetaClass(domainClassToMock)
+ protected void saveDomainList(PersistentEntity entity, List domains) {
+ for (obj in domains) {
+ if (obj instanceof Map) {
+ entity.javaClass.newInstance(obj).save()
+ } else if (entity.isInstance(obj)) {
+ obj.save()
+ }
+ }
+ }
- ControllersGrailsPlugin.enhanceDomainWithBinding(applicationContext, domain, mc)
- DomainClassGrailsPlugin.registerConstraintsProperty(mc, domain)
-// DomainClassGrailsPlugin.addRelationshipManagementMethods(domain, applicationContext)
- def validationBeanName = "${domain.fullName}Validator"
+ protected void enhanceSingleEntity(PersistentEntity entity) {
+ def enhancer = new GormEnhancer(simpleDatastore, transactionManager)
+ if (entity.javaClass.getAnnotation(Enhanced) != null) {
+ enhancer.enhance(entity, true)
+ } else {
+ enhancer.enhance(entity)
+ }
+ }
+
+ protected Validator registerDomainClassValidator(GrailsDomainClass domain) {
+ String validationBeanName = "${domain.fullName}Validator"
defineBeans {
"${domain.fullName}"(domain.clazz) { bean ->
bean.singleton = false
@@ -151,27 +198,16 @@ class DomainClassUnitTestMixin extends GrailsUnitTestMixin {
}
def validator = applicationContext.getBean(validationBeanName, Validator.class)
- simpleDatastore.mappingContext.addEntityValidator(entity, validator)
+ validator
+ }
- def enhancer = new GormEnhancer(simpleDatastore, transactionManager)
- if (domainClassToMock.getAnnotation(Enhanced) != null) {
- enhancer.enhance(entity, true)
- }
- else {
- enhancer.enhance(entity)
- }
- if (domains) {
- for (obj in domains) {
- if (obj instanceof Map) {
- domainClassToMock.newInstance(obj).save()
- }
- else if (entity.isInstance(obj)) {
- obj.save()
- }
- }
- }
- else {
- return applicationContext.getBean(domain.fullName)
- }
+ protected GrailsDomainClass registerGrailsDomainClass(Class domainClassToMock) {
+ GrailsDomainClass domain = grailsApplication.addArtefact(DomainClassArtefactHandler.TYPE, domainClassToMock)
+
+ final mc = GrailsClassUtils.getExpandoMetaClass(domainClassToMock)
+
+ ControllersGrailsPlugin.enhanceDomainWithBinding(applicationContext, domain, mc)
+ DomainClassGrailsPlugin.registerConstraintsProperty(mc, domain)
+ return domain
}
}
View
20 ...rc/main/groovy/org/codehaus/groovy/grails/compiler/injection/test/MockTransformation.java
@@ -17,6 +17,7 @@
import grails.test.mixin.Mock;
+import grails.test.mixin.domain.DomainClassUnitTestMixin;
import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
@@ -28,6 +29,9 @@
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.GroovyASTTransformation;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Used by the {@link grails.test.mixin.Mock} local transformation to add
* mocking capabilities for the given classes.
@@ -68,10 +72,24 @@ public void visit(ASTNode[] astNodes, SourceUnit source) {
return;
}
+ List<ClassExpression> domainClassNodes = new ArrayList<ClassExpression>();
for (Expression expression : values.getExpressions()) {
if (expression instanceof ClassExpression) {
- weaveMock(classNode, (ClassExpression)expression, false);
+ ClassExpression classEx = (ClassExpression) expression;
+ ClassNode cn = classEx.getType();
+ Class mixinClassForArtefactType = getMixinClassForArtefactType(cn);
+ if(mixinClassForArtefactType != null) {
+
+ weaveMock(classNode, classEx, false);
+ }
+ else {
+ domainClassNodes.add(classEx);
+ }
}
}
+ if(!domainClassNodes.isEmpty()) {
+ weaveMixinClass(classNode, DomainClassUnitTestMixin.class);
+ addMockCollaborators(classNode, "Domain", domainClassNodes);
+ }
}
}
View
63 ...main/groovy/org/codehaus/groovy/grails/compiler/injection/test/TestForTransformation.java
@@ -270,33 +270,61 @@ protected MethodNode weaveMock(ClassNode classNode, ClassExpression value, boole
return testForMethod;
}
+ protected Class getMixinClassForArtefactType(ClassNode classNode) {
+ String className = classNode.getName();
+ for (String artefactType : artefactTypeToTestMap.keySet()) {
+ if (className.endsWith(artefactType)) {
+ Class mixinClass = artefactTypeToTestMap.get(artefactType);
+ if(mixinClass != null) {
+ return mixinClass;
+ }
+ }
+ }
+ return null;
+ }
+
+
private void addMockCollaboratorToSetup(ClassNode classNode, ClassExpression targetClassExpression, String artefactType) {
+ BlockStatement methodBody = getOrCreateTestSetupMethod(classNode);
+ addMockCollaborator(artefactType, targetClassExpression,methodBody);
+ }
+ protected BlockStatement getOrCreateTestSetupMethod(ClassNode classNode) {
BlockStatement methodBody;
if (isJunit3Test(classNode)) {
methodBody = getJunit3Setup(classNode);
- addMockCollaborator(artefactType, targetClassExpression,methodBody);
}
else {
- addToJunit4BeforeMethods(classNode, artefactType, targetClassExpression);
+ methodBody = getExistingOrCreateJUnit4Setup(classNode);
}
+ return methodBody;
}
private void addToJunit4BeforeMethods(ClassNode classNode, String artefactType, ClassExpression targetClassExpression) {
+ BlockStatement junit4Setup = getExistingOrCreateJUnit4Setup(classNode);
+ addMockCollaborator(artefactType,targetClassExpression,junit4Setup);
+ }
+
+ protected BlockStatement getExistingOrCreateJUnit4Setup(ClassNode classNode) {
+ Statement code = getExistingJUnit4BeforeMethod(classNode);
+ if(code instanceof BlockStatement) {
+ return (BlockStatement) code;
+ }
+ else {
+ return getJunit4Setup(classNode);
+ }
+
+ }
+
+ protected Statement getExistingJUnit4BeforeMethod(ClassNode classNode) {
+ Statement code = null;
Map<String, MethodNode> declaredMethodsMap = classNode.getDeclaredMethodsMap();
- boolean weavedIntoBeforeMethods = false;
for (MethodNode methodNode : declaredMethodsMap.values()) {
if (isDeclaredBeforeMethod(methodNode)) {
- Statement code = getMethodBody(methodNode);
- addMockCollaborator(artefactType, targetClassExpression, (BlockStatement) code);
- weavedIntoBeforeMethods = true;
+ code = getMethodBody(methodNode);
}
}
-
- if (!weavedIntoBeforeMethods) {
- BlockStatement junit4Setup = getJunit4Setup(classNode);
- addMockCollaborator(artefactType,targetClassExpression,junit4Setup);
- }
+ return code;
}
private Statement getMethodBody(MethodNode methodNode) {
@@ -432,4 +460,17 @@ protected void addMockCollaborator(String mockType, ClassExpression targetClass,
args.addExpression(targetClass);
methodBody.getStatements().add(0, new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "mock" + mockType, args)));
}
+
+ protected void addMockCollaborators(ClassNode classNode, String mockType, List<ClassExpression> targetClasses) {
+ addMockCollaborators(mockType, targetClasses, getOrCreateTestSetupMethod(classNode));
+ }
+
+
+ protected void addMockCollaborators(String mockType, List<ClassExpression> targetClasses, BlockStatement methodBody) {
+ ArgumentListExpression args = new ArgumentListExpression();
+ for(ClassExpression ce : targetClasses) {
+ args.addExpression(ce);
+ }
+ methodBody.getStatements().add(0, new ExpressionStatement(new MethodCallExpression(THIS_EXPRESSION, "mock" + mockType + 's', args)));
+ }
}

0 comments on commit 6dfab1a

Please sign in to comment.
Something went wrong with that request. Please try again.