Skip to content

Commit 6adb23b

Browse files
bsideupkiview
andauthored
Fix Spock's TestLifecycleAware integration (#2563)
* Fix Spock's `TestLifecycleAware` integration * Small cleanups Co-authored-by: Kevin Wittek <[email protected]>
1 parent 95c828d commit 6adb23b

File tree

4 files changed

+112
-104
lines changed

4 files changed

+112
-104
lines changed

modules/spock/src/main/groovy/org/testcontainers/spock/TestcontainersMethodInterceptor.groovy

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {
3030
invocation.proceed()
3131
}
3232

33+
@Override
3334
void interceptCleanupSpecMethod(IMethodInvocation invocation) throws Throwable {
3435
def containers = findAllContainers(true)
3536
stopContainers(containers, invocation)
@@ -54,13 +55,6 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {
5455

5556
@Override
5657
void interceptCleanupMethod(IMethodInvocation invocation) throws Throwable {
57-
findAllTestLifecycleAwareContainers(invocation).each {
58-
// we assume first error is the one we want
59-
def maybeException = Optional.ofNullable(errorListener.errors[0]?.exception)
60-
def testDescription = SpockTestDescription.fromTestDescription(invocation)
61-
it.afterTest(testDescription, maybeException)
62-
}
63-
6458
def containers = findAllContainers(false)
6559
stopContainers(containers, invocation)
6660

@@ -76,14 +70,6 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {
7670
}
7771
}
7872

79-
private List<TestLifecycleAware> findAllTestLifecycleAwareContainers(IMethodInvocation invocation) {
80-
spec.allFields.findAll { FieldInfo f ->
81-
TestLifecycleAware.isAssignableFrom(f.type)
82-
}.collect {
83-
it.readValue(invocation.instance) as TestLifecycleAware
84-
}
85-
}
86-
8773
private List<FieldInfo> findAllComposeContainers(boolean shared) {
8874
spec.allFields.findAll { FieldInfo f ->
8975
DockerComposeContainer.isAssignableFrom(f.type) && f.shared == shared
@@ -96,12 +82,25 @@ class TestcontainersMethodInterceptor extends AbstractMethodInterceptor {
9682
if(!container.isRunning()){
9783
container.start()
9884
}
85+
86+
if (container instanceof TestLifecycleAware) {
87+
def testDescription = SpockTestDescription.fromTestDescription(invocation)
88+
(container as TestLifecycleAware).beforeTest(testDescription)
89+
}
9990
}
10091
}
10192

102-
private static void stopContainers(List<FieldInfo> containers, IMethodInvocation invocation) {
93+
private void stopContainers(List<FieldInfo> containers, IMethodInvocation invocation) {
10394
containers.each { FieldInfo f ->
10495
GenericContainer container = readContainerFromField(f, invocation)
96+
97+
if (container instanceof TestLifecycleAware) {
98+
// we assume first error is the one we want
99+
def maybeException = Optional.ofNullable(errorListener.errors[0]?.exception)
100+
def testDescription = SpockTestDescription.fromTestDescription(invocation)
101+
(container as TestLifecycleAware).afterTest(testDescription, maybeException)
102+
}
103+
105104
container.stop()
106105
}
107106
}

modules/spock/src/test/groovy/org/testcontainers/spock/BrowserVncRecordingIT.groovy

Lines changed: 0 additions & 88 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.testcontainers.spock;
2+
3+
import org.testcontainers.containers.GenericContainer;
4+
import org.testcontainers.lifecycle.TestDescription;
5+
import org.testcontainers.lifecycle.TestLifecycleAware;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Optional;
10+
11+
public class TestLifecycleAwareContainerMock extends GenericContainer<TestLifecycleAwareContainerMock> implements TestLifecycleAware {
12+
13+
static final String BEFORE_TEST = "beforeTest";
14+
static final String AFTER_TEST = "afterTest";
15+
16+
final List<String> lifecycleMethodCalls = new ArrayList<>();
17+
final List<String> lifecycleFilesystemFriendlyNames = new ArrayList<>();
18+
19+
Throwable capturedThrowable;
20+
21+
@Override
22+
public void beforeTest(TestDescription description) {
23+
lifecycleMethodCalls.add(BEFORE_TEST);
24+
lifecycleFilesystemFriendlyNames.add(description.getFilesystemFriendlyName());
25+
}
26+
27+
@Override
28+
public void afterTest(TestDescription description, Optional<Throwable> throwable) {
29+
lifecycleMethodCalls.add(AFTER_TEST);
30+
throwable.ifPresent(capturedThrowable -> this.capturedThrowable = capturedThrowable);
31+
}
32+
33+
@Override
34+
public void start() {
35+
// Do nothing
36+
}
37+
38+
@Override
39+
public void stop() {
40+
// Do nothing
41+
}
42+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package org.testcontainers.spock
2+
3+
import org.intellij.lang.annotations.Language
4+
import spock.lang.Specification
5+
import spock.lang.Unroll
6+
import spock.util.EmbeddedSpecRunner
7+
8+
class TestLifecycleAwareIT extends Specification {
9+
10+
@Unroll("When failing test is #fails, afterTest receives '#filesystemFriendlyNames' and throwable starting with message '#errorMessageStartsWith'")
11+
def "lifecycle awareness"() {
12+
given:
13+
14+
@Language("groovy")
15+
String myTest = """
16+
import org.testcontainers.spock.Testcontainers
17+
import org.testcontainers.containers.GenericContainer
18+
import spock.lang.Specification
19+
20+
@Testcontainers
21+
class TestLifecycleAwareIT extends Specification {
22+
23+
GenericContainer container = System.properties["org.testcontainers.container"] as GenericContainer
24+
25+
def "perform test"() {
26+
expect:
27+
!System.properties["org.testcontainers.shouldFail"]
28+
}
29+
}
30+
"""
31+
and:
32+
def container = new TestLifecycleAwareContainerMock()
33+
System.properties["org.testcontainers.container"] = container
34+
System.properties["org.testcontainers.shouldFail"] = fails
35+
36+
when: "executing the test"
37+
def runner = new EmbeddedSpecRunner(throwFailure: false)
38+
runner.run(myTest)
39+
40+
then: "mock container received lifecycle calls as expected"
41+
container.lifecycleMethodCalls == ["beforeTest", "afterTest"]
42+
container.lifecycleFilesystemFriendlyNames.join(",") == filesystemFriendlyNames
43+
if (errorMessageStartsWith) {
44+
assert container.capturedThrowable.message.startsWith(errorMessageStartsWith)
45+
} else {
46+
assert container.capturedThrowable == null
47+
}
48+
49+
where:
50+
fails | filesystemFriendlyNames | errorMessageStartsWith
51+
false | 'TestLifecycleAwareIT-perform+test' | null
52+
true | 'TestLifecycleAwareIT-perform+test' | "Condition not satisfied:"
53+
}
54+
55+
}

0 commit comments

Comments
 (0)