diff --git a/provider/junit5spring/src/test/java/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderTest.java b/provider/junit5spring/src/test/java/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderTest.java new file mode 100644 index 0000000000..bbc9fddb47 --- /dev/null +++ b/provider/junit5spring/src/test/java/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderTest.java @@ -0,0 +1,76 @@ +package au.com.dius.pact.provider.spring.junit5; + +import org.junit.jupiter.api.Test; + +import au.com.dius.pact.provider.junitsupport.loader.PactBrokerConsumerVersionSelectors; +import au.com.dius.pact.provider.junitsupport.loader.PactBrokerLoader; +import au.com.dius.pact.provider.junitsupport.loader.SelectorBuilder; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class PactBrokerLoaderTest { + + @Test + void test1() { + assertNotNull(PactBrokerLoader.testClassHasSelectorsMethod(Test1.class)); + } + + @Test + void test2() { + assertThrows(IllegalAccessException.class, () -> PactBrokerLoader.testClassHasSelectorsMethod(Test2.class)); + } + + @Test + void test3() { + assertThrows(IllegalAccessException.class, () -> PactBrokerLoader.testClassHasSelectorsMethod(Test3.class)); + } + + @Test + void test4() { + assertThrows(IllegalAccessException.class, () -> PactBrokerLoader.testClassHasSelectorsMethod(Test4.class)); + } + + @Test + void test5() { + assertNotNull(PactBrokerLoader.testClassHasSelectorsMethod(Test5.class)); + } + + static class Test1 { + @PactBrokerConsumerVersionSelectors + public static SelectorBuilder cvs() { + return new SelectorBuilder(); + } + } + static class Test2 { + @PactBrokerConsumerVersionSelectors + static SelectorBuilder cvs() { + return new SelectorBuilder(); + } + } + + static class Test3 { + @PactBrokerConsumerVersionSelectors + private static SelectorBuilder cvs() { + return new SelectorBuilder(); + } + } + + class Test4 extends Test4Super {} + + static class Test4Super { + @PactBrokerConsumerVersionSelectors + protected static SelectorBuilder cvs() { + return new SelectorBuilder(); + } + } + + class Test5 extends Test5Super {} + + static class Test5Super { + @PactBrokerConsumerVersionSelectors + public static SelectorBuilder cvs() { + return new SelectorBuilder(); + } + } +} diff --git a/provider/junit5spring/src/test/kotlin/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderKtTest.kt b/provider/junit5spring/src/test/kotlin/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderKtTest.kt new file mode 100644 index 0000000000..1018e048ec --- /dev/null +++ b/provider/junit5spring/src/test/kotlin/au/com/dius/pact/provider/spring/junit5/PactBrokerLoaderKtTest.kt @@ -0,0 +1,101 @@ +package au.com.dius.pact.provider.spring.junit5 + +import au.com.dius.pact.provider.junitsupport.loader.PactBrokerConsumerVersionSelectors +import au.com.dius.pact.provider.junitsupport.loader.PactBrokerLoader.Companion.testClassHasSelectorsMethod +import au.com.dius.pact.provider.junitsupport.loader.SelectorBuilder +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Assertions.assertThrows +import org.junit.jupiter.api.Test + +class PactBrokerLoaderKtTest { + + @Test + fun test1() { + assertNotNull(testClassHasSelectorsMethod(Test1::class.java)) + } + + @Test + fun test2() { + assertThrows(IllegalAccessException::class.java) { + testClassHasSelectorsMethod(Test2::class.java) + } + } + + @Test + fun test3() { + assertThrows(IllegalAccessException::class.java) { + testClassHasSelectorsMethod(Test3::class.java) + } + } + + @Test + fun test4() { + assertThrows(IllegalAccessException::class.java) { + testClassHasSelectorsMethod(Test4::class.java) + } + } + + @Test + fun test5() { + assertNotNull(testClassHasSelectorsMethod(Test5::class.java)) + } + + @Test + fun test6() { + assertNotNull(testClassHasSelectorsMethod(Test6::class.java)) + } + + class Test1 { + @PactBrokerConsumerVersionSelectors + fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + + class Test2 { + @PactBrokerConsumerVersionSelectors + private fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + + class Test3 { + @PactBrokerConsumerVersionSelectors + private fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + + class Test4 : Test4Super() + + @Suppress("UnnecessaryAbstractClass") + abstract class Test4Super { + + @PactBrokerConsumerVersionSelectors + protected fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + + class Test5 : Test5Super() + + @Suppress("UnnecessaryAbstractClass") + abstract class Test5Super { + @PactBrokerConsumerVersionSelectors + fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + + class Test6 : Test6Super() + + @Suppress("UnnecessaryAbstractClass") + abstract class Test6Super() { + companion object { + @PactBrokerConsumerVersionSelectors + fun cvs(): SelectorBuilder { + return SelectorBuilder() + } + } + } +} \ No newline at end of file diff --git a/provider/src/main/kotlin/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoader.kt b/provider/src/main/kotlin/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoader.kt index 6bb4285602..7887c3127e 100644 --- a/provider/src/main/kotlin/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoader.kt +++ b/provider/src/main/kotlin/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoader.kt @@ -24,17 +24,18 @@ import com.github.michaelbull.result.Ok import mu.KLogging import org.apache.http.client.utils.URIBuilder import java.io.IOException +import java.lang.reflect.Method import java.lang.reflect.Modifier import java.net.URI import java.net.URISyntaxException -import kotlin.reflect.KCallable import kotlin.reflect.KClass import kotlin.reflect.KFunction -import kotlin.reflect.KParameter -import kotlin.reflect.KVisibility -import kotlin.reflect.full.findAnnotation +import kotlin.reflect.full.companionObject +import kotlin.reflect.full.declaredFunctions +import kotlin.reflect.full.hasAnnotation import kotlin.reflect.full.isSubtypeOf import kotlin.reflect.full.starProjectedType +import kotlin.reflect.jvm.javaMethod import kotlin.reflect.jvm.kotlinFunction /** @@ -352,7 +353,7 @@ open class PactBrokerLoader( companion object : KLogging() { @JvmStatic - fun invokeSelectorsMethod(testInstance: Any?, selectorsMethod: KCallable<*>): List { + fun invokeSelectorsMethod(testInstance: Any?, selectorsMethod: KFunction<*>): List { val projectedType = SelectorBuilder::class.starProjectedType return when (selectorsMethod.parameters.size) { 0 -> if (selectorsMethod.returnType.isSubtypeOf(projectedType)) { @@ -373,10 +374,9 @@ open class PactBrokerLoader( } @JvmStatic + @Suppress("ThrowsCount") fun testClassHasSelectorsMethod(testClass: Class<*>?): KFunction<*>? { - val method = testClass?.methods?.firstOrNull { method -> - method.getAnnotation(PactBrokerConsumerVersionSelectors::class.java) != null - } + val method = findConsumerVersionSelectorAnnotatedMethod(testClass) if (method != null) { if (method.parameterCount > 0) { @@ -404,5 +404,35 @@ open class PactBrokerLoader( return method?.kotlinFunction } + + @OptIn(ExperimentalStdlibApi::class) + private fun findConsumerVersionSelectorAnnotatedMethod(testClass: Class<*>?) : Method? { + if (testClass == null) { + return null + } + + var klass : Class<*> = testClass + while (klass != Object::class.java) { + + for (declaredMethod in klass.declaredMethods) { + if (declaredMethod.isAnnotationPresent(PactBrokerConsumerVersionSelectors::class.java)) { + return declaredMethod + } + + val method = klass.kotlin.companionObject?.declaredFunctions?.firstOrNull { + it.hasAnnotation() + } + + if (method != null) { + return method.javaMethod + } + } + + klass = klass.superclass + } + + return null + } + } } diff --git a/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoaderSpec.groovy b/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoaderSpec.groovy index a629c36f5f..5d4247d4b0 100644 --- a/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoaderSpec.groovy +++ b/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/PactBrokerLoaderSpec.groovy @@ -1442,7 +1442,6 @@ class PactBrokerLoaderSpec extends Specification { null | false PactBrokerLoaderSpec | false FullPactBrokerAnnotation | false - IncorrectScopeOnSelectorMethod | false CorrectSelectorMethod | true CorrectSelectorMethod2 | true CorrectSelectorMethod3 | true @@ -1460,7 +1459,7 @@ class PactBrokerLoaderSpec extends Specification { thrown(IllegalAccessException) where: - clazz << [IncorrectTypesOnSelectorMethod, IncorrectTypesOnSelectorMethod2 ] + clazz << [ IncorrectTypesOnSelectorMethod, IncorrectTypesOnSelectorMethod2, IncorrectScopeOnSelectorMethod ] } @Unroll diff --git a/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/SelectorBuilderSpec.groovy b/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/SelectorBuilderSpec.groovy index 649bfd9ae9..3ea10956aa 100644 --- a/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/SelectorBuilderSpec.groovy +++ b/provider/src/test/groovy/au/com/dius/pact/provider/junitsupport/loader/SelectorBuilderSpec.groovy @@ -6,6 +6,7 @@ import static au.com.dius.pact.core.support.JsonKt.jsonArray class SelectorBuilderSpec extends Specification { + @SuppressWarnings('UnnecessaryCollectCall') def 'allow providing selectors in raw form'() { expect: jsonArray(new SelectorBuilder()