Pact-jvm: Maven Pact-Verification

Created on 27 Jun 2017  路  24Comments  路  Source: pact-foundation/pact-jvm

I am new to using pact-jvm, and I think I have completed my consumer tests, and I'm wondering how to produce my pact file, and how to test it against my provider. I'm looking at the example in the ReadMe, but I feel I may be misunderstanding it. Can anyone give any insight or examples? I'm using maven.

All 24 comments

Attached is my pom file, and my test code. When I ran mvn install on the pom file, it is a successful build and a target folder is created, but it doesn't produce a pact.
pomcapture
testcapture

I can't see anything blatantly wrong, but your POM file should have the pact junit dependency as a test scope. Also, you are not providing the port of the mockProvider to your application (it will be a random one), I'm guessing that the test is failing because the mock provider did not receive any requests, and thus no pact files are being generated.

@uglyog thanks I've tried using the pact-junit dependency with a test scope, but it always gives me build errors when I do so. I have updated my project, but I am still not getting a pact product produced, here is my updated pom and test files:
updatedpom
updatedtest
Any suggestions?

Please provide the build errors.

@uglyog Hi, so when I use junit with a scope of 'test', I get an errors that the dependent package does not exist and all my imports fail.
Also, here is my updated test class, but I am still not able to get a pact file produced despite a successful build.

updatedtest

Can you provide the dependent package and imports that are failing? mvn dependency:tree can be used to diagnose dependency issues. See https://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html

@uglyog So I changed the scope of pact-jvm-consumer-junit_2.11 and when I ran mvn dependency:tree, I did not receive any errors or conflict messages:
dependencytree

When I attempted to run mvn clean install I still received a build error of:
capture

Here's the update in the pom file:
updatedpom

@uglyog I think I may have resolved the error with the scope. Now I am able to use the pact-jvm-consumer-junit_2.11 dependency with a test scope, but I am now receiving a maven-surefire-error that says "The forked VM terminated without saying properly goodbye. VM crash or System.exit calld ? ".
The entire stack trace is as follows:
surefireerror
surefireerror2

I am working as part of a team, and we'd really love to use the PACT Framework, but we may need a bit more guidance to meet a deadline approaching soon. Is there anyway we could work out a time to speak to you over the phone, and work through some of our questions?

I have spotted the dependency problem. You are requiring pact-jvm-consumer-junit-2.11 and pact-jvm-consumer-2.11 versions 3.4.1, but pact-jvm-model_2.11 version 2.4.15. These are not compatible.

You need to remove the pact-jvm-model_2.11 from the dependencies, then the correct library pact-jvm-model version 3.4.1 will be pulled in (no _2.11 in the name).

The second stack trace is because the Groovy dependency is missing. I have no idea why it is not being included, but you may need to add it directly:

<dependency>
  <groupId>org.codehaus.groovy</groupId>
  <artifactId>groovy-all</artifactId>
  <version>2.4.10</version>
  <scope>test</scope>
</dependency>

If you want, we could organise a time to chat on the gitter channel (see the link on the main README), but please be mindful of timezone differences, I am based in Australia.

@uglyog Thanks so much that cleared many things up! I think I am closer to producing a pact file, but I'm not sure where the code in my test class is going wrong. Is it necessary to have an "assertEquals" statement in my runTest() method to get a pact file?
Here's my code:
updatedtest

With this code, I get a successful build, but no pact file is produced.

When I have the following in my runTest() method
Client newClient = new Client(mockProvider.getUrl());
newClient.getBody();
I get the following error:
capture

Also, we'd be happy to work around the time differences to chat with you. Is there a day you're available? What's the earliest time in the morning (in Australian time) that you'd be available and willing to chat?

@mcgriffa - You are passing a specific client IP and port where as the mockserver would be running on a different port as you have not specified in your PactProviderRuleMk2 initialization.

And don't forget to import
import au.com.dius.pact.consumer.MockServer;

public final PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider-1", "localhost", 8096, this);

And change runTest to take in a mockServer parameter.

 protected void runTest(MockServer mockServer) {
        try {
            Client newClient = new Client(mockServer.getUrl()).getAsMap('/greeting', '');
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

I think this should resolve the issue assuming you have the function of getAsMap implemented in Client class as in the example on the pact-jvm repository. (https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit/src/test/java/au/com/dius/pact/consumer/exampleclients/ConsumerClient.java#L31)

My Client class is not like that of the example, I just wrote this simple one that returns response.

Also, when I insert the MockServer parameters inside of the runTest() method, I get an error that says that runTest() should have no parameters.

public Client(String givenUrl) {

    this.BASE_URL = givenUrl;
}

public String getBody() {

    String output = "";
    try {
        URL url = new URL(BASE_URL);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Accept", "application/json");
        //System.out.println(conn.getInputStream());

        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        // if ((output = br.readLine()) != null) {
        output = br.readLine();
        // }
        // System.out.println(conn.getContentType());
        conn.disconnect();

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return output;

}

got it. But still you don't mention port explicitly in your PactProviderRuleMk2 rule, so sending in localhost:8080 would not be right as the mock server is running on a different port . does that make sense ?

why don't you try putting the port explicitly in the provider rule ?
public final PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider-1", "localhost", 8080, this);

Also your provider name on the provider rule and other places are not the same

Yes that makes sense. I saw some examples that had something like this:
``public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider-1", this);

and in the runTest() it was something like:
``assertEquals(expectedResponse, new Client(mockProvider.getUrl).getBody());

But for some reason that resulted in some sort of URL error when I tried it, and I'm not sure if it's due to my Client class or because of the way I'm calling the mocProvider in the test class.

got it.
we don't any assertions, you can skip that to start with, try to print this mockProvider.getPort() to get to know that you are pointing to the correct port.
And also correct the provider name in both these lines

  • @PactVerification("test_provider-1")
  • @Pact(provider="test_provider-1", consumer = "test-consumer-1")

I take back part of what I said.
My tests extends the new class ConsumerPactTestMk2 which has to override this abstract method --> runTest(MockServer), so I use MockServer which works fine.

But your ConsumerTest doesn't seem to extend any class.
FYI
And in this commit, you can see PactProviderRuleMK2 uses new mockServer - https://github.com/DiUS/pact-jvm/commit/a74962573965471379ae2525286823744e2a0fba - So I think using that would make it work as I do use mockServer and it works fine.

There are two options:

Extend your test class from ConsumerPactTestMk2 and then have a runtest method that takes a mock server, as @shashidesai mentioned. Example here: https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit/src/test/java/au/com/dius/pact/consumer/examples/StatusServiceConsumerPactTest.java

Or

Use the PactProviderRuleMk2 which is a JUnit rule (as you have been doing). In this case you need to access the provider rule class in your test method to get to the port of the mock server. Example here: https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit/src/test/java/au/com/dius/pact/consumer/examples/ExampleJavaConsumerPactRuleTest.java

Just be aware that the provider class will return a null for the URL or port if called outside of the test method.

The other option is to use a specific port. Here is an example test that uses a specific port: https://github.com/DiUS/pact-jvm/blob/master/pact-jvm-consumer-junit/src/test/java/au/com/dius/pact/consumer/examples/ArticlesTest.java

I will be available to answer questions in the gitter channel 9am to 5pm and 7pm to 9pm AEST (which is +10) most week days. Just give me a heads up to get onto the gitter channel.

Thanks so much @uglyog and @shashidesai! I think your tips and hints kind of got me in the right direction.
I think I'm having bit of a dependency issue now. I'm getting that the class au.com.dius.pact.model.RequestMatching is not defined, and I know I have the au.com.dius.pact.model dependency taken care of. When I look inside of that package though, the RequestMatching class is not present, is there a different "model" package that I need to manually install and put into my pom file?
capture

You maven is definitely not resolving transitive dependencies correctly. RequestMatching is in library pact-jvm-matchers_2.11.

@uglyog thanks . I'll be sure to resolve that dependency. My team and I are working behind a firewall, so most of the dependencies we've had to resolve manually.

We still will try to join the Gitter chat on Tuesday (your time) to chat with you, and ask some other questions. Thanks so much .

Hi @mcgriffa!
Just in case you are still having trouble using jUnit Rules and Pact annotations, you should check your @Pact and @PactVerification annotated methods are "public" and not "protected" like in your screenshots ;)

Good pickup @vverrier! I didn't even notice that.

Was this page helpful?
0 / 5 - 0 ratings