diff --git a/pom.xml b/pom.xml
index eb9f3ff..c7de760 100644
--- a/pom.xml
+++ b/pom.xml
@@ -117,6 +117,12 @@
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 4.0.4
+ test
+
@@ -183,5 +189,10 @@
wildfly-common
test
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
\ No newline at end of file
diff --git a/src/main/resources/META-INF/jqassistant-plugin.xml b/src/main/resources/META-INF/jqassistant-plugin.xml
index 372e32b..697cbca 100644
--- a/src/main/resources/META-INF/jqassistant-plugin.xml
+++ b/src/main/resources/META-INF/jqassistant-plugin.xml
@@ -12,5 +12,6 @@
camunda-bpmn.xml
projectreactor.xml
wildfly-assert.xml
+ spring-reactive.xml
diff --git a/src/main/resources/META-INF/jqassistant-rules/spring-reactive.xml b/src/main/resources/META-INF/jqassistant-rules/spring-reactive.xml
new file mode 100644
index 0000000..bcf7d5e
--- /dev/null
+++ b/src/main/resources/META-INF/jqassistant-rules/spring-reactive.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ Sets labels :Assert and :Spring:Reactive for Spring Reactive WebTestClient assert methods.
+
+ (assertMethod)
+ WHERE
+ assertType.fqn =~ 'org\\.springframework\\.test\\.web\\.reactive\\.server\\.WebTestClient\\$ResponseSpec'
+ AND assertMethod.signature =~ '.* expect.*'
+ SET
+ assertMethod:Spring:Reactive:Assert
+ RETURN
+ assertMethod
+ ORDER BY
+ assertMethod.signature
+ ]]>
+
+
+
diff --git a/src/test/java/org/jqassistant/plugin/java_testing/concept/AssertExample.java b/src/test/java/org/jqassistant/plugin/java_testing/concept/AssertExample.java
index 6255035..31f0aff 100644
--- a/src/test/java/org/jqassistant/plugin/java_testing/concept/AssertExample.java
+++ b/src/test/java/org/jqassistant/plugin/java_testing/concept/AssertExample.java
@@ -5,6 +5,7 @@
import org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests;
import org.mockito.BDDMockito;
import org.mockito.MockedStatic;
+import org.springframework.test.web.reactive.server.WebTestClient;
import org.wildfly.common.Assert;
import org.xmlunit.assertj.XmlAssert;
import reactor.test.StepVerifier;
@@ -59,4 +60,9 @@ void wildflyAssertExampleMethod() {
Assert.assertTrue(true);
}
+ void springWebTestClientAssertExampleMethod() {
+ WebTestClient webTestClient = mock(WebTestClient.class);
+ webTestClient.get().exchange().expectStatus().isOk();
+ }
+
}
\ No newline at end of file
diff --git a/src/test/java/org/jqassistant/plugin/java_testing/concept/SpringReactiveWebTestClientIT.java b/src/test/java/org/jqassistant/plugin/java_testing/concept/SpringReactiveWebTestClientIT.java
new file mode 100644
index 0000000..279d651
--- /dev/null
+++ b/src/test/java/org/jqassistant/plugin/java_testing/concept/SpringReactiveWebTestClientIT.java
@@ -0,0 +1,80 @@
+package org.jqassistant.plugin.java_testing.concept;
+
+import com.buschmais.jqassistant.core.report.api.model.Column;
+import com.buschmais.jqassistant.core.report.api.model.Result;
+import com.buschmais.jqassistant.core.report.api.model.Row;
+import com.buschmais.jqassistant.core.rule.api.model.Concept;
+import com.buschmais.jqassistant.core.test.plugin.AbstractPluginIT;
+import com.buschmais.jqassistant.plugin.java.api.model.MethodDescriptor;
+import com.buschmais.jqassistant.plugin.java.api.model.TypeDescriptor;
+import com.buschmais.jqassistant.plugin.java.test.AbstractJavaPluginIT;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.buschmais.jqassistant.core.report.api.model.Result.Status.SUCCESS;
+import static com.buschmais.jqassistant.plugin.java.test.assertj.MethodDescriptorCondition.methodDescriptor;
+import static com.buschmais.jqassistant.plugin.java.test.assertj.TypeDescriptorCondition.typeDescriptor;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.InstanceOfAssertFactories.type;
+
+public class SpringReactiveWebTestClientIT extends AbstractJavaPluginIT {
+
+ @Test
+ void springReactiveWebTestClientAssertMethod() throws Exception {
+ scanClasses(AssertExample.class);
+
+ final Result conceptResult = applyConcept("java-testing-spring-reactive:AssertMethod");
+ assertThat(conceptResult.getStatus()).isEqualTo(SUCCESS);
+
+ store.beginTransaction();
+
+ assertThat(conceptResult.getRows().size()).isEqualTo(1);
+ assertThat(conceptResult.getRows()
+ .get(0)
+ .getColumns()
+ .get("assertMethod")
+ .getValue()).asInstanceOf(type(MethodDescriptor.class))
+ .is(methodDescriptor(WebTestClient.ResponseSpec.class, "expectStatus"));
+
+ verifyResultGraph();
+
+ store.commitTransaction();
+ }
+
+ @Test
+ void providedConceptAssertMethod() throws Exception {
+ scanClasses(AssertExample.class);
+
+ final Result conceptResult = applyConcept("java:AssertMethod");
+ assertThat(conceptResult.getStatus()).isEqualTo(SUCCESS);
+
+ store.beginTransaction();
+
+ final List declaringTypes = conceptResult.getRows().stream()
+ .map(Row::getColumns)
+ .map(columns -> columns.get("DeclaringType"))
+ .map(Column::getValue)
+ .map(TypeDescriptor.class::cast)
+ .collect(Collectors.toList());
+ assertThat(declaringTypes).haveExactly(1, typeDescriptor(WebTestClient.ResponseSpec.class));
+
+ verifyResultGraph();
+
+ store.commitTransaction();
+ }
+
+ // Expects an open transaction
+ private void verifyResultGraph() throws NoSuchMethodException {
+ final AbstractPluginIT.TestResult methodQueryResult = query(
+ "MATCH (testMethod:Method)-[:INVOKES]->(assertMethod:Method) "
+ + "WHERE assertMethod:Spring:Reactive:Assert "
+ + "RETURN testMethod, assertMethod");
+ assertThat(methodQueryResult.getColumn("testMethod"))
+ .haveExactly(1, methodDescriptor(AssertExample.class, "springWebTestClientAssertExampleMethod"));
+ assertThat(methodQueryResult.getColumn("assertMethod"))
+ .haveExactly(1, methodDescriptor(WebTestClient.ResponseSpec.class, "expectStatus"));
+ }
+}