Skip to content

Commit 011e5d5

Browse files
RNieslergraemerocher
authored andcommitted
Do not rollback transaction in jUnit @before and @after methods (#10029)
1 parent 1223031 commit 011e5d5

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

grails-core/src/main/groovy/org/grails/transaction/transform/TransactionalTransform.groovy

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class TransactionalTransform implements ASTTransformation{
7575
private static final String METHOD_EXECUTE = "execute"
7676
private static final Set<String> METHOD_NAME_EXCLUDES = new HashSet<String>(Arrays.asList("afterPropertiesSet", "destroy"));
7777
private static final Set<String> ANNOTATION_NAME_EXCLUDES = new HashSet<String>(Arrays.asList(PostConstruct.class.getName(), PreDestroy.class.getName(), Transactional.class.getName(), Rollback.class.getName(), "grails.web.controllers.ControllerMethod", NotTransactional.class.getName()));
78+
private static final Set<String> JUNIT_ANNOTATION_NAMES = new HashSet<String>(Arrays.asList("org.junit.Before", "org.junit.After"));
7879
private static final String SPEC_CLASS = "spock.lang.Specification";
7980
public static final String PROPERTY_DATA_SOURCE = "datasource"
8081

@@ -116,7 +117,8 @@ class TransactionalTransform implements ASTTransformation{
116117
for (MethodNode md in methods) {
117118
String methodName = md.getName()
118119
int modifiers = md.modifiers
119-
if (!md.isSynthetic() && Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers) && !Modifier.isStatic(modifiers)) {
120+
if (!md.isSynthetic() && Modifier.isPublic(modifiers) && !Modifier.isAbstract(modifiers) &&
121+
!Modifier.isStatic(modifiers) && !hasJunitAnnotation(md)) {
120122
if(hasExcludedAnnotation(md)) continue
121123

122124
def startsWithSpock = methodName.startsWith('$spock')
@@ -138,7 +140,8 @@ class TransactionalTransform implements ASTTransformation{
138140
if(hasAnnotation(md, DelegatingMethod.class)) continue
139141
weaveTransactionalMethod(source, classNode, annotationNode, md);
140142
}
141-
else if(("setup".equals(methodName) || "cleanup".equals(methodName)) && isSpockTest(classNode)) {
143+
else if ((("setup".equals(methodName) || "cleanup".equals(methodName)) && isSpockTest(classNode)) ||
144+
hasJunitAnnotation(md)) {
142145
def requiresNewTransaction = new AnnotationNode(annotationNode.classNode)
143146
requiresNewTransaction.addMember("propagation", new PropertyExpression(new ClassExpression(ClassHelper.make(Propagation.class)), "REQUIRES_NEW"))
144147
weaveTransactionalMethod(source, classNode, requiresNewTransaction, md, "execute")
@@ -161,6 +164,17 @@ class TransactionalTransform implements ASTTransformation{
161164
excludedAnnotation
162165
}
163166

167+
private boolean hasJunitAnnotation(MethodNode md) {
168+
boolean excludedAnnotation = false;
169+
for (AnnotationNode annotation : md.getAnnotations()) {
170+
if(JUNIT_ANNOTATION_NAMES.contains(annotation.getClassNode().getName())) {
171+
excludedAnnotation = true;
172+
break;
173+
}
174+
}
175+
excludedAnnotation
176+
}
177+
164178
ClassNode getAnnotationClassNode(String annotationName) {
165179
try {
166180
final classLoader = Thread.currentThread().contextClassLoader

grails-core/src/test/groovy/grails/transaction/TransactionalTransformSpec.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,46 @@ class TransactionalTransformSpec extends Specification {
9494

9595
}
9696

97+
void "Test @Rollback when applied to JUnit specifications"() {
98+
when:
99+
Class mySpec = new GroovyShell().evaluate('''
100+
import grails.transaction.*
101+
import org.junit.Test
102+
import org.junit.Before
103+
import org.junit.After
104+
105+
@Rollback
106+
class MyJunitTest {
107+
@Before
108+
def junitSetup() {
109+
110+
}
111+
112+
@After
113+
def junitCleanup() {
114+
115+
}
116+
117+
@Test
118+
void junitTest() {
119+
expect:
120+
1 == 1
121+
}
122+
}
123+
MyJunitTest
124+
''')
125+
126+
then: "It implements TransactionManagerAware"
127+
TransactionManagerAware.isAssignableFrom(mySpec)
128+
mySpec.getDeclaredMethod('junitSetup')
129+
mySpec.getDeclaredMethod('$tt__junitSetup', TransactionStatus)
130+
mySpec.getDeclaredMethod('junitCleanup')
131+
mySpec.getDeclaredMethod('$tt__junitCleanup', TransactionStatus)
132+
133+
mySpec.getDeclaredMethod('junitTest')
134+
mySpec.getDeclaredMethod('$tt__junitTest', TransactionStatus)
135+
}
136+
97137
void "Test @Rollback when applied to Spock specifications"() {
98138
when: "A new instance of a class with a @Transactional method is created that subclasses another transactional class"
99139
Class mySpec = new GroovyShell().evaluate('''

0 commit comments

Comments
 (0)