Skip to content

Commit

Permalink
Fix #157 - Support @before* and @after* methods; Restore ordering sim…
Browse files Browse the repository at this point in the history
…ilar to JUnit 4/Spock ordering (#428)

Fix #157 - Support @before* and @after* methods; Restore ordering similar to JUnit 4/Spock ordering
  • Loading branch information
jdaugherty committed Sep 26, 2024
1 parent 9de8c00 commit aadb56d
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package org.grails.testing.spock

import grails.testing.spock.OnceBefore
import grails.testing.spring.AutowiredTest
import groovy.transform.CompileStatic
import org.grails.testing.GrailsUnitTest
import org.junit.After
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.spockframework.runtime.extension.AbstractGlobalExtension
import org.spockframework.runtime.extension.IGlobalExtension
import org.spockframework.runtime.model.MethodInfo
import org.spockframework.runtime.model.MethodKind
import org.spockframework.runtime.model.SpecInfo
Expand All @@ -17,7 +17,7 @@ import java.lang.reflect.Method
import java.lang.reflect.Modifier

@CompileStatic
class TestingSupportExtension extends AbstractGlobalExtension {
class TestingSupportExtension implements IGlobalExtension {

AutowiredInterceptor autowiredInterceptor = new AutowiredInterceptor()
CleanupContextInterceptor cleanupContextInterceptor = new CleanupContextInterceptor()
Expand All @@ -30,39 +30,49 @@ class TestingSupportExtension extends AbstractGlobalExtension {
if (GrailsUnitTest.isAssignableFrom(spec.reflection)) {
spec.addCleanupSpecInterceptor(cleanupContextInterceptor)
}
for (Method method : spec.getReflection().getDeclaredMethods()) {
for (Method method : (spec.getReflection().declaredMethods)) {
if (method.isAnnotationPresent(BeforeEach.class)) {
spec.addSetupMethod(createJUnitFixtureMethod(spec, method, MethodKind.SETUP, BeforeEach.class));
spec.setupMethods.add(0, createJUnitFixtureMethod(spec, method, MethodKind.SETUP, BeforeEach.class))
}
if (method.isAnnotationPresent(AfterEach.class)) {
spec.addCleanupMethod(createJUnitFixtureMethod(spec, method, MethodKind.CLEANUP, AfterEach.class))
}
if (method.isAnnotationPresent(BeforeAll.class)) {
spec.setupSpecMethods.add(0, createJUnitFixtureMethod(spec, method, MethodKind.SETUP_SPEC, BeforeAll.class))
}
if (method.isAnnotationPresent(AfterAll.class)) {
spec.addCleanupSpecMethod(createJUnitFixtureMethod(spec, method, MethodKind.CLEANUP_SPEC, AfterAll.class))
}
}
}

private MethodInfo createMethod(SpecInfo specInfo, Method method, MethodKind kind, String name) {
MethodInfo methodInfo = new MethodInfo();
methodInfo.setParent(specInfo);
methodInfo.setName(name);
methodInfo.setReflection(method);
methodInfo.setKind(kind);
return methodInfo;
private static MethodInfo createMethod(SpecInfo specInfo, Method method, MethodKind kind, String name) {
MethodInfo methodInfo = new MethodInfo()
methodInfo.parent = specInfo
methodInfo.name = name
methodInfo.reflection = method
methodInfo.kind = kind
return methodInfo
}

private MethodInfo createJUnitFixtureMethod(SpecInfo specInfo, Method method, MethodKind kind, Class<? extends Annotation> annotation) {
MethodInfo methodInfo = createMethod(specInfo, method, kind, method.getName());
methodInfo.setExcluded(isOverriddenJUnitFixtureMethod(specInfo, method, annotation));
return methodInfo;
private static MethodInfo createJUnitFixtureMethod(SpecInfo specInfo, Method method, MethodKind kind, Class<? extends Annotation> annotation) {
MethodInfo methodInfo = createMethod(specInfo, method, kind, method.name)
methodInfo.excluded = isOverriddenJUnitFixtureMethod(specInfo, method, annotation)
return methodInfo
}
private boolean isOverriddenJUnitFixtureMethod(SpecInfo specInfo, Method method, Class<? extends Annotation> annotation) {
if (Modifier.isPrivate(method.getModifiers())) return false;

for (Class<?> currClass = specInfo.class; currClass != specInfo.class.superclass; currClass = currClass.getSuperclass()) {
for (Method currMethod : currClass.getDeclaredMethods()) {
if (!currMethod.isAnnotationPresent(annotation)) continue;
if (!currMethod.getName().equals(method.getName())) continue;
if (!Arrays.deepEquals(currMethod.getParameterTypes(), method.getParameterTypes())) continue;
return true;
private static boolean isOverriddenJUnitFixtureMethod(SpecInfo specInfo, Method method, Class<? extends Annotation> annotation) {
if (Modifier.isPrivate(method.modifiers)) return false

for (Class<?> currClass = specInfo.class; currClass != specInfo.class.superclass; currClass = currClass.superclass) {
for (Method currMethod : currClass.declaredMethods) {
if (!currMethod.isAnnotationPresent(annotation)) continue
if (currMethod.name != method.name) continue
if (!Arrays.deepEquals(currMethod.parameterTypes, method.parameterTypes)) continue
return true
}
}

return false;
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package grails.testing.spock

import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Stepwise

@Stepwise
class JUnitAnnotationSpec extends Specification {
@Shared
static List<String> methodOrder = []

void setupSpec() {
methodOrder << "setupSpec"
}

void setup() {
methodOrder << "setup"
}

void cleanup() {
methodOrder << "cleanup"
}

void cleanupSpec() {
methodOrder << "cleanupSpec"
}

@BeforeEach
void beforeEach() {
methodOrder << "beforeEach"
}

@AfterEach
void afterEach() {
methodOrder << "afterEach"
}

@BeforeAll
static void beforeAll() {
methodOrder << "beforeAll"
}

@AfterAll
static void afterAll() {
methodOrder << "afterAll"
assert methodOrder == ["beforeAll", "setupSpec", "beforeEach", "setup", "cleanup", "afterEach", "cleanupSpec", "afterAll"]
}

void 'junit 5 annotated methods are called in correct order prior to this test'() {
expect:
methodOrder == ["beforeAll", "setupSpec", "beforeEach", "setup"]
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package grails.testing.spock

import org.junit.Before
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Stepwise
Expand Down

0 comments on commit aadb56d

Please sign in to comment.