Skip to content

[Java] Process glue classes distinctly #2582

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Jul 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Removed

### Fixed
- [Java] Process glue classes distinctly ([#2582](https://github.com/cucumber/cucumber-jvm/pull/2582) M.P. Korstanje)

## [7.4.1] (2022-06-23)

Expand Down
1 change: 1 addition & 0 deletions guice/src/main/java/io/cucumber/guice/GuiceBackend.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public void loadGlue(Glue glue, List<URI> gluePaths) {
.map(classFinder::scanForClassesInPackage)
.flatMap(Collection::stream)
.filter(InjectorSource.class::isAssignableFrom)
.distinct()
.forEach(container::addClass);
}

Expand Down
10 changes: 10 additions & 0 deletions guice/src/test/java/io/cucumber/guice/GuiceBackendTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
import java.util.function.Supplier;

import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@ExtendWith({ MockitoExtension.class })
Expand All @@ -39,6 +41,14 @@ void finds_injector_source_impls_by_classpath_url() {
verify(factory).addClass(YourInjectorSource.class);
}

@Test
void finds_injector_source_impls_once_by_classpath_url() {
GuiceBackend backend = new GuiceBackend(factory, classLoader);
backend.loadGlue(glue, asList(URI.create("classpath:io/cucumber/guice/integration"),
URI.create("classpath:io/cucumber/guice/integration")));
verify(factory, times(1)).addClass(YourInjectorSource.class);
}

@Test
void world_and_snippet_methods_do_nothing() {
GuiceBackend backend = new GuiceBackend(factory, classLoader);
Expand Down
1 change: 1 addition & 0 deletions java/src/main/java/io/cucumber/java/JavaBackend.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public void loadGlue(Glue glue, List<URI> gluePaths) {
.map(ClasspathSupport::packageName)
.map(classFinder::scanForClassesInPackage)
.flatMap(Collection::stream)
.distinct()
.forEach(aGlueClass -> scan(aGlueClass, (method, annotation) -> {
container.addClass(method.getDeclaringClass());
glueAdaptor.addDefinition(method, annotation);
Expand Down
11 changes: 10 additions & 1 deletion java/src/test/java/io/cucumber/java/JavaBackendTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.net.URI;
import java.util.Arrays;
import java.util.List;

import static java.lang.Thread.currentThread;
Expand All @@ -27,7 +28,7 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@ExtendWith({ MockitoExtension.class })
@ExtendWith(MockitoExtension.class)
class JavaBackendTest {

@Captor
Expand All @@ -53,6 +54,14 @@ void finds_step_definitions_by_classpath_url() {
verify(factory).addClass(Steps.class);
}

@Test
void finds_step_definitions_once_by_classpath_url() {
backend.loadGlue(glue,
asList(URI.create("classpath:io/cucumber/java/steps"), URI.create("classpath:io/cucumber/java/steps")));
backend.buildWorld();
verify(factory, times(1)).addClass(Steps.class);
}

@Test
void detects_subclassed_glue_and_throws_exception() {
Executable testMethod = () -> backend.loadGlue(glue, asList(URI.create("classpath:io/cucumber/java/steps"),
Expand Down
1 change: 1 addition & 0 deletions java8/src/main/java/io/cucumber/java8/Java8Backend.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public void loadGlue(Glue glue, List<URI> gluePaths) {
.flatMap(Collection::stream)
.filter(glueClass -> !glueClass.isInterface())
.filter(glueClass -> glueClass.getConstructors().length > 0)
.distinct()
.forEach(glueClass -> {
container.addClass(glueClass);
lambdaGlueClasses.add(glueClass);
Expand Down
13 changes: 12 additions & 1 deletion java8/src/test/java/io/cucumber/java8/Java8BackendTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.net.URI;
import java.util.Arrays;

import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@ExtendWith({ MockitoExtension.class })
@ExtendWith(MockitoExtension.class)
class Java8BackendTest {

@Mock
Expand All @@ -38,4 +41,12 @@ void finds_step_definitions_by_classpath_url() {
verify(factory).addClass(Steps.class);
}

@Test
void finds_step_definitions_once_by_classpath_url() {
backend.loadGlue(glue,
asList(URI.create("classpath:io/cucumber/java8/steps"), URI.create("classpath:io/cucumber/java8/steps")));
backend.buildWorld();
verify(factory, times(1)).addClass(Steps.class);
}

}
7 changes: 7 additions & 0 deletions spring/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<junit-jupiter.version>5.8.2</junit-jupiter.version>
<spring.version>5.3.21</spring.version>
<project.Automatic-Module-Name>io.cucumber.spring</project.Automatic-Module-Name>
<mockito.version>4.6.1</mockito.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -109,6 +110,12 @@
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
3 changes: 2 additions & 1 deletion spring/src/main/java/io/cucumber/spring/SpringBackend.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ public void loadGlue(Glue glue, List<URI> gluePaths) {
.map(ClasspathSupport::packageName)
.map(classFinder::scanForClassesInPackage)
.flatMap(Collection::stream)
.filter((Class clazz) -> clazz.getAnnotation(CucumberContextConfiguration.class) != null)
.filter((Class<?> clazz) -> clazz.getAnnotation(CucumberContextConfiguration.class) != null)
.distinct()
.forEach(container::addClass);
}

Expand Down
55 changes: 55 additions & 0 deletions spring/src/test/java/io/cucumber/spring/SpringBackendTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.cucumber.spring;

import io.cucumber.core.backend.Glue;
import io.cucumber.core.backend.ObjectFactory;
import io.cucumber.core.backend.StepDefinition;
import io.cucumber.spring.annotationconfig.AnnotationContextConfiguration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.net.URI;

import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@ExtendWith(MockitoExtension.class)
class SpringBackendTest {

@Mock
private Glue glue;

@Mock
private ObjectFactory factory;

private SpringBackend backend;

@BeforeEach
void createBackend() {
this.backend = new SpringBackend(factory, currentThread()::getContextClassLoader);
}

@Test
void finds_annotation_context_configuration_by_classpath_url() {
backend.loadGlue(glue, singletonList(URI.create("classpath:io/cucumber/spring/annotationconfig")));
backend.buildWorld();
verify(factory).addClass(AnnotationContextConfiguration.class);
}

@Test
void finds_annotaiton_context_configuration_once_by_classpath_url() {
backend.loadGlue(glue, asList(
URI.create("classpath:io/cucumber/spring/annotationconfig"),
URI.create("classpath:io/cucumber/spring/annotationconfig")));
backend.buildWorld();
verify(factory, times(1)).addClass(AnnotationContextConfiguration.class);
}

}