Skip to content

Commit 383ab6d

Browse files
[Java] Fix duplicate step defintion when using interfaces (#2759)
Co-authored-by: Julien Kronegg <julien [at] kronegg.ch> Co-authored-by: M.P. Korstanje <[email protected]>
1 parent b53204e commit 383ab6d

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
### Fixed
1414
- [Core] Fixed `cucumber.publish.enabled=false` ([#2747](https://github.com/cucumber/cucumber-jvm/pull/2747) M.P. Korstanje)
1515
- [JUnit Platform Engine] Fixed `cucumber.publish.enabled=false` ([#2747](https://github.com/cucumber/cucumber-jvm/pull/2747) M.P. Korstanje)
16+
- [Java] Fixed duplicate step definition for classes with interfaces ([#2757](https://github.com/cucumber/cucumber-jvm/issues/2757) Julien Kronegg)
1617

1718
## [7.12.0] - 2023-04-29
1819
### Added

cucumber-java/src/main/java/io/cucumber/java/MethodScanner.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ private static void scan(BiConsumer<Method, Annotation> consumer, Class<?> aClas
5555
if (Object.class.equals(method.getDeclaringClass())) {
5656
return;
5757
}
58+
59+
// exclude bridge methods: when a class implements a method
60+
// from the interface but specializes the return type, two methods will
61+
// be generated. One with the return type of the interface and one
62+
// with the specialized return type. The former is a bridge method.
63+
// Depending on the JVM, the method annotations are also applied to
64+
// the bridge method.
65+
if (method.isBridge()) {
66+
return;
67+
}
68+
5869
scan(consumer, aClass, method, method.getAnnotations());
5970
}
6071

cucumber-java/src/test/java/io/cucumber/java/JavaBackendTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.mockito.junit.jupiter.MockitoExtension;
1515

1616
import java.net.URI;
17-
import java.util.Arrays;
1817
import java.util.List;
1918

2019
import static java.lang.Thread.currentThread;

cucumber-java/src/test/java/io/cucumber/java/MethodScannerTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.cucumber.java;
22

3+
import io.cucumber.java.en.Given;
34
import org.junit.jupiter.api.BeforeEach;
45
import org.junit.jupiter.api.Test;
56

@@ -41,6 +42,13 @@ void scan_ignores_object() {
4142
assertThat(scanResult, empty());
4243
}
4344

45+
@Test
46+
void scan_ignores_bridge_methods() throws NoSuchMethodException {
47+
Method method = SpecializedReturnType.class.getMethod("test");
48+
MethodScanner.scan(SpecializedReturnType.class, backend);
49+
assertThat(scanResult, contains(new SimpleEntry<>(method, method.getAnnotations()[0])));
50+
}
51+
4452
@Test
4553
void scan_ignores_non_instantiable_class() {
4654
MethodScanner.scan(NonStaticInnerClass.class, backend);
@@ -81,4 +89,17 @@ public void m() {
8189

8290
}
8391

92+
public interface GenericReturnType {
93+
Number test();
94+
95+
}
96+
97+
public static class SpecializedReturnType implements GenericReturnType {
98+
99+
@Given("test")
100+
public Integer test() {
101+
return 1;
102+
}
103+
104+
}
84105
}

0 commit comments

Comments
 (0)