Skip to content

Commit

Permalink
fix(JUnit5): Provider name can be provided with the @Pact annotation #…
Browse files Browse the repository at this point in the history
  • Loading branch information
rholshausen committed Apr 12, 2023
1 parent 8a70a1a commit 2070ce5
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
val methodAnnotation = pactTestForTestMethod(context)
val classAnnotation = pactTestForClass(context)

val providerInfo = when {
var providerInfo = when {
classAnnotation != null && methodAnnotation != null ->
ProviderInfo.fromAnnotation(methodAnnotation)
.merge(ProviderInfo.fromAnnotation(classAnnotation))
Expand All @@ -383,24 +383,14 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
providerInfo != null -> {
when {
methodAnnotation != null -> if (methodAnnotation.pactMethods.isNotEmpty()) {
buildProviderList(methodAnnotation, context, providerInfo)
buildProviderListFromPactMethods(methodAnnotation, context, providerInfo)
} else {
val mockServerConfig = mockServerConfigFromAnnotation(context, providerInfo)
val provider = providerInfo.withMockServerConfig(mockServerConfig)
val pactMethods = if (methodAnnotation.pactMethod.isNotEmpty())
listOf(methodAnnotation.pactMethod)
else emptyList()
listOf(provider to pactMethods)
buildProviderListFromPactMethod(methodAnnotation, context, providerInfo)
}
classAnnotation != null -> if (classAnnotation.pactMethods.isNotEmpty()) {
buildProviderList(classAnnotation, context, providerInfo)
buildProviderListFromPactMethods(classAnnotation, context, providerInfo)
} else {
val mockServerConfig = mockServerConfigFromAnnotation(context, providerInfo)
val provider = providerInfo.withMockServerConfig(mockServerConfig)
val pactMethods = if (classAnnotation.pactMethod.isNotEmpty())
listOf(classAnnotation.pactMethod)
else emptyList()
listOf(provider to pactMethods)
buildProviderListFromPactMethod(classAnnotation, context, providerInfo)
}
else -> {
logger.warn { "No @PactTestFor annotation found on test class, using defaults" }
Expand All @@ -423,7 +413,24 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal
return providerInfo
}

private fun buildProviderList(
private fun buildProviderListFromPactMethod(
annotation: PactTestFor,
context: ExtensionContext,
provider: ProviderInfo
): List<Pair<ProviderInfo, List<String>>> {
var providerInfo = provider
val pactMethod = if (annotation.pactMethod.isNotEmpty()) {
val providerName = providerNameFromPactMethod(annotation.pactMethod, context)
if (providerName.isNotEmpty()) {
providerInfo = providerInfo.copy(providerName = providerName)
}
listOf(annotation.pactMethod)
} else emptyList()
val mockServerConfig = mockServerConfigFromAnnotation(context, providerInfo)
return listOf(providerInfo.withMockServerConfig(mockServerConfig) to pactMethod)
}

private fun buildProviderListFromPactMethods(
annotation: PactTestFor,
context: ExtensionContext,
providerInfo: ProviderInfo
Expand Down Expand Up @@ -478,7 +485,7 @@ class PactConsumerTestExt : Extension, BeforeTestExecutionCallback, BeforeAllCal

private fun providerNameFromPactMethod(methodName: String, context: ExtensionContext): String {
val method = pactMethodAnnotation(null, context, methodName)
return method!!.getAnnotation(Pact::class.java).provider
return method?.getAnnotation(Pact::class.java)?.provider.orEmpty()
}

fun lookupPact(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,51 @@ class PactConsumerTestExtSpec extends Specification {
providerInfo.first().second == ['pactMethod1', 'pactMethod2']
}

@PactTestFor
static class TestClassWithProviderOnPactAnnotation {
@Pact(provider = 'TestClassWithProviderOnPactAnnotation')
RequestResponsePact pactMethod(PactDslWithProvider builder) {
builder
.uponReceiving('interaction 1')
.path('/one')
.toPact()
}

@PactTestFor(pactMethods = [ 'pactMethod' ])
def pactTestForMethod() { }

@PactTestFor(pactMethod = 'pactMethod')
def pactTestForMethod2() { }
}

def 'lookupProviderInfo - with provider name on the pact method - pactMethods'() {
given:
testMethod = TestClassWithProviderOnPactAnnotation.getMethod('pactTestForMethod')
requiredTestClass = TestClassWithProviderOnPactAnnotation

when:
def providerInfo = testExt.lookupProviderInfo(mockContext)

then:
providerInfo.size() == 1
providerInfo.first().first.providerName == 'TestClassWithProviderOnPactAnnotation'
providerInfo.first().second == ['pactMethod']
}

def 'lookupProviderInfo - with provider name on the pact method - pactMethod'() {
given:
testMethod = TestClassWithProviderOnPactAnnotation.getMethod('pactTestForMethod2')
requiredTestClass = TestClassWithProviderOnPactAnnotation

when:
def providerInfo = testExt.lookupProviderInfo(mockContext)

then:
providerInfo.size() == 1
providerInfo.first().first.providerName == 'TestClassWithProviderOnPactAnnotation'
providerInfo.first().second == ['pactMethod']
}

def 'mockServerConfigured - returns false when there are no MockServerConfig annotations'() {
expect:
!testExt.mockServerConfigured(mockContext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class PactConsumerTestExtTest {
hostInterface = 'localhost', port = '8080', pactVersion = PactSpecVersion.V3)
class TestClassWithClassLevelAnnotation {
@SuppressWarnings('UnusedMethodParameter')
@Pact
RequestResponsePact pactMethod(PactDslWithProvider builder) {
pact
}
Expand All @@ -67,6 +68,7 @@ class PactConsumerTestExtTest {
@SuppressWarnings('UnusedMethodParameter')
@PactTestFor(providerName = 'TestClassWithMethodLevelAnnotation', pactMethod = 'pactMethod',
hostInterface = 'localhost', port = '8080', pactVersion = PactSpecVersion.V3)
@Pact
RequestResponsePact pactMethod(PactDslWithProvider builder) {
pact
}
Expand All @@ -77,6 +79,7 @@ class PactConsumerTestExtTest {
class TestClassWithMethodAndClassLevelAnnotation {
@SuppressWarnings('UnusedMethodParameter')
@PactTestFor(pactMethod = 'pactMethod', hostInterface = 'testServer')
@Pact
RequestResponsePact pactMethod(PactDslWithProvider builder) {
pact
}
Expand All @@ -87,6 +90,7 @@ class PactConsumerTestExtTest {
class TestClassWithMethodAndClassLevelAnnotation2 {
@SuppressWarnings('UnusedMethodParameter')
@PactTestFor(pactMethod = 'pactMethod', hostInterface = 'testServer', pactVersion = PactSpecVersion.V3)
@Pact
RequestResponsePact pactMethod(PactDslWithProvider builder) {
pact
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package au.com.dius.pact.consumer.junit5;

import au.com.dius.pact.consumer.MockServer;
import au.com.dius.pact.consumer.dsl.PactDslRootValue;
import au.com.dius.pact.consumer.dsl.PactDslWithProvider;
import au.com.dius.pact.consumer.junit.MockServerConfig;
import au.com.dius.pact.core.model.PactSpecVersion;
import au.com.dius.pact.core.model.V4Pact;
import au.com.dius.pact.core.model.annotations.Pact;
import io.restassured.RestAssured;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.util.Map;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

@ExtendWith(PactConsumerTestExt.class)
@PactTestFor(pactVersion = PactSpecVersion.V4)
@MockServerConfig(providerName = "rest-heroes", port = PactMultiProviderTest.HEROES_PORT, hostInterface = "localhost")
@MockServerConfig(providerName = "rest-villains", port = PactMultiProviderTest.VILLAINS_PORT, hostInterface = "localhost")
public class PactMultiProviderTest {
static final String HEROES_PORT = "1234";
static final String VILLAINS_PORT = "1235";

@Pact(consumer = "rest-fights", provider = "rest-heroes")
public V4Pact helloHeroesPact(PactDslWithProvider builder) {
return builder
.uponReceiving("A hello request")
.path("/hello/hero")
.method("GET")
.willRespondWith()
.headers(Map.of("Content-Type", "text/plain"))
.status(200)
.body(PactDslRootValue.stringMatcher(".+", "Hello Heroes!"))
.toPact(V4Pact.class);
}

@Pact(consumer = "rest-fights", provider = "rest-villains")
public V4Pact helloVillainsPact(PactDslWithProvider builder) {
return builder
.uponReceiving("A hello request")
.path("/hello/villain")
.method("GET")
.willRespondWith()
.headers(Map.of("Content-Type", "text/plain"))
.status(200)
.body(PactDslRootValue.stringMatcher(".+", "Hello Villains!"))
.toPact(V4Pact.class);
}

@Test
@PactTestFor(pactMethods = { "helloHeroesPact", "helloVillainsPact" })
public void helloHeroesAndVillains(@ForProvider("rest-heroes") MockServer heroesMockServer, @ForProvider("rest-villains") MockServer villainsMockServer) {
assertThat(heroesMockServer.getPort(), is(Integer.parseInt(HEROES_PORT)));

assertThat(villainsMockServer.getPort(), is(Integer.parseInt(VILLAINS_PORT)));

testHelloHeroes();
testHelloVillains();
}

@Test
@PactTestFor(pactMethod = "helloHeroesPact")
public void helloHeroes(@ForProvider("rest-heroes") MockServer mockServer) {
assertThat(mockServer.getPort(), is(Integer.parseInt(HEROES_PORT)));

testHelloHeroes();
}

@Test
@PactTestFor(pactMethod = "helloVillainsPact")
public void helloVillains(@ForProvider("rest-villains") MockServer mockServer) {
assertThat(mockServer.getPort(), is(Integer.parseInt(VILLAINS_PORT)));

testHelloVillains();
}

private void testHelloHeroes() {
RestAssured.given()
.port(Integer.parseInt(HEROES_PORT))
.when().get("/hello/hero").then()
.statusCode(200)
.contentType("text/plain")
.body(is("Hello Heroes!"));
}

private void testHelloVillains() {
RestAssured.given()
.port(Integer.parseInt(VILLAINS_PORT))
.when().get("/hello/villain").then()
.statusCode(200)
.contentType("text/plain")
.body(is("Hello Villains!"));
}
}

0 comments on commit 2070ce5

Please sign in to comment.