Showing posts with label JUnit. Show all posts
Showing posts with label JUnit. Show all posts

Tuesday, March 14, 2017

Consumer Driven Testing with Pact & Spring Boot

Recently a colleague of mine stumbled across Pact.io,  Our current application had grown to over 50 services and we we're starting to have some integration test failures and a brittle dev / acceptance test environment. So we decided to have a look at ways to try help with this.

I started out by reading:
https://docs.pact.io/faq/convinceme.html

Then watching:
https://www.youtube.com/watch?v=-6x6XBDf9sQ&feature=youtu.be

Those 2 resources convinced me to give it a shot.

So I set out and created a quick set of Spring boot apps, the GitHub repo here, to test out the concepts and get everything working.

To highlight some important bits from the demo.

Consumer:
As Pact is a consumer driven test framework. This is where you define a unit test, that test mocks the http server response and you assert against that.
Once the test is successful it creates a pact json file in the /pacts directory.

So after the "mock" test is run and the pact file has been created. You need to include a maven plugin ...pact... that is then used to publish the content of the pacts/ folder to the pact broker... which is defined in the pom as below.

Producer:

This uses the JUnit integration from Pact.io to download the pacts from the broker and then run against an running service.

Since this already uses a @RunWith annotation, I could not use the spring boot runner. So to get around that as a before class step, I start the Spring boot application, the pacts then gets run against that running instance... and the boot application gets stopped again after the tests. Depending on your use case I guess it would also be an option to do this with @Before so you get a new service instance started before each pack, but that would slow down the execution tremendously.

The @State annotation, allows for clients to define a specific state, which the producer can the use to setup additional data / conditions required for the test to run.

Once the pacts have executed against the service there are reports generated in the target folder.




Setting up the Pact Broker

1. Grab the public images from Docker Hub.
docker pull dius/pact_broker
docker pull postgres

2. Then setup the Postgres DB
docker run --name pactbroker-db -e POSTGRES_PASSWORD=ThePostgresPassword -e POSTGRES_USER=admin -d postgres
docker run -it --link pactbroker-db:postgres --rm postgres psql -h postgres -U admin
CREATE USER pactbrokeruser WITH PASSWORD 'TheUserPassword';
CREATE DATABASE pactbroker WITH OWNER pactbrokeruser;
GRANT ALL PRIVILEGES ON DATABASE pactbroker TO pactbrokeruser;
3. Once the DB is up, run the actual Broker:
docker run --name pactbroker --link pactbroker-db:postgres -e PACT_BROKER_DATABASE_USERNAME=pactbrokeruser -e PACT_BROKER_DATABASE_PASSWORD=TheUserPassword -e PACT_BROKER_DATABASE_HOST=postgres -e PACT_BROKER_DATABASE_NAME=pactbroker -d -p 80:80 dius/pact_broker


Extra References:

https://docs.pact.io/documentation/
https://docs.pact.io/documentation/sharings_pacts.html
https://github.com/DiUS/pact-jvm
https://github.com/DiUS/pact-jvm/tree/master/pact-jvm-consumer-junit

Get the example project
https://github.com/bdupreez/pactdemo


Monday, May 31, 2010

Spring 3: OXM... Castor, JAXB, JibX and xmlBeans (And XStream)

Updated to include XStream

Another reason to love Spring... OXM...

Basically there are 5 common Object to XML mapping projects out there... Castor, JaxB, XStream ,JibX and xmlBeans. Since I am lazy an a fan of reuse I won't be going into JibX as this other blogger (Guido Schumtz) did it quite nicely:
JibX Maven Spring OXM

I won't describe xmlBeans either, 'cause as soon as I saw that the objects need to extend XmlObject I lost interest... I don't wanna have to change my class hierarchy just to do mappings, that is so very 90's.

I did however slap together a quick Castor, JaxB and XStream example:
You need a bean that you want to map in and out of xml in this case (ClassToXMLMap.java)
package javaitzen.spring.oxm;

import javax.xml.bind.annotation.XmlRootElement;
import com.thoughtworks.xstream.annotations.XStreamAlias;

@XmlRootElement(name="ClassToXMLMap")
@XStreamAlias( "ClassToXMLMap" )
public class ClassToXMLMap {
 private String data;
 private String history;
 
 public String getData() {
  return data;
 }
 
 public void setData(String data) {
  this.data = data;
 }
 
 public String getHistory() {
  return history;
 }
 
 public void setHistory(String history) {
  this.history = history;
 } 
}


Then a class to use the Spring marshallers:
package javaitzen.spring.oxm;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class OXMarshall {
    
    private Marshaller marshaller;
    private Unmarshaller unmarshaller;

    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }

    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }

    public void saveXML(ClassToXMLMap message, String fileName) throws IOException {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(fileName);
            this.marshaller.marshal(message, new StreamResult(fos));
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

    public ClassToXMLMap loadXML(String fileName) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(fileName);
            return (ClassToXMLMap) this.unmarshaller.unmarshal(new StreamSource(fis));
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
    }    
}


The JUnit Test:
package javaitzen.spring.oxm;

import static org.junit.Assert.assertNotNull;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@ContextConfiguration(locations={"/javaitzen/spring/oxm/applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class OXMTest {

 @Autowired
 OXMarshall castor;
 
 @Autowired
 OXMarshall jax;

 @Autowired
 OXMarshall xtream;
 
 ClassToXMLMap message;
 
 @Before
 public void setup(){
     message = new ClassToXMLMap();
     message.setData("I am data");
     message.setHistory("in the past");
 }
 
 @Test
 public void testCastor() throws Exception{
  String castorFile = "castor.xml";
  castor.saveXML(message, castorFile);
        assertNotNull(castor.loadXML(castorFile));
 }
 
 @Test
 public void testJaxB() throws Exception{
  String jaxbFile = "jaxb.xml";
     jax.saveXML(message,jaxbFile);
        assertNotNull(jax.loadXML(jaxbFile));
 }

 @Test
 public void testXStream() throws Exception{
        String xtreamFile = "xtream.xml";
        xtream.saveXML(message,xtreamFile);
        assertNotNull(xtream.loadXML(xtreamFile));
    }
 
}


The mapping file for Castor:



The application context for the Test:


Hint: If you want to use xmlBeans or JibX there are tags defined for them by Spring, and you will be able to substitute them for the ones in my example.



Last but not least the Maven pom file:

Building KubeSkippy: Learnings from a thought experiment

So, I got Claude Code Max and I thought of what would be the most ambitious thing I could try "vibe"? As my team looks after Kuber...