Provides a Java8 lambda based DSL for use with Junit to build consumer tests.
This is an extension for the pact DSL provided by pact-jvm-consumer. The difference between the default pact DSL and this lambda DSL is, as the name suggests, the usage of lambdas. The use of lambdas makes the code much cleaner.
The lambda DSL solves the following two main issues. Both are visible in the following code sample:
new PactDslJsonArray()
.array() # open an array
.stringValue("a1") # choose the method that is valid for arrays
.stringValue("a2") # choose the method that is valid for arrays
.closeArray() # close the array
.array() # open an array
.numberValue(1) # choose the method that is valid for arrays
.numberValue(2) # choose the method that is valid for arrays
.closeArray() # close the array
.array() # open an array
.object() # now we work with an object
.stringValue("foo", "Foo") # choose the method that is valid for objects
.closeObject() # close the object and we're back in the array
.closeArray() # close the array
Methods may only be called in certain states. For example object()
may only be called when you're currently working on an array whereas object(name)
is only allowed to be called when working on an object. But both of the methods are available. You'll find out at runtime if you're using the correct method.
Finally, the need for opening and closing objects and arrays makes usage cumbersome.
The lambda DSL has no ambiguous methods and there's no need to close objects and arrays as all the work on such an object is wrapped in a lamda call.
When formatting your source code with an IDE the code becomes hard to read as there's no indentation possible. Of course, you could do it by hand but we want auto formatting! Auto formatting works great for the new DSL!
array.object((o) -> {
o.stringValue("foo", "Foo"); # an attribute
o.stringValue("bar", "Bar"); # an attribute
o.object("tar", (tarObject) -> { # an attribute with a nested object
tarObject.stringValue("a", "A"); # attribute of the nested object
tarObject.stringValue("b", "B"); # attribute of the nested object
})
});
<dependency>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-consumer-java8</artifactId>
<version>${pact.version}</version>
</dependency>
Start with a static import of LambdaDsl
. This class contains factory methods for the lambda dsl extension.
When you come accross the body()
method of PactDslWithProvider
builder start using the new extensions.
The call to LambdaDsl
replaces the call to instance new PactDslJsonArray()
and new PactDslJsonBody()
of the pact library.
io.pactfoundation.consumer.dsl.LambdaDsl.*
import static io.pactfoundation.consumer.dsl.LambdaDsl.newJsonArray;
...
PactDslWithProvider builder = ...
builder.given("some state")
.uponReceiving("a request")
.path("/my-app/my-service")
.method("GET")
.willRespondWith()
.status(200)
.body(newJsonArray((a) -> {
a.stringValue("a1");
a.stringValue("a2");
}).build());
import static io.pactfoundation.consumer.dsl.LambdaDsl.newJsonBody;
...
PactDslWithProvider builder = ...
builder.given("some state")
.uponReceiving("a request")
.path("/my-app/my-service")
.method("GET")
.willRespondWith()
.status(200)
.body(newJsonBody((o) -> {
o.stringValue("foo", "Foo");
o.stringValue("bar", "Bar");
}).build());
When creating simple json structures the difference between the two approaches isn't big.
{
"bar": "Bar",
"foo": "Foo"
}
new PactDslJsonBody()
.stringValue("foo", "Foo")
.stringValue("bar", "Bar")
newJsonBody((o) -> {
o.stringValue("foo", "Foo");
o.stringValue("bar", "Bar");
}).build()
When we come to more complex constructs with arrays and nested objects the beauty of lambdas become visible!
[
["a1", "a2"],
[1, 2],
[{"foo": "Foo"}]
]
new PactDslJsonArray()
.array()
.stringValue("a1")
.stringValue("a2")
.closeArray()
.array()
.numberValue(1)
.numberValue(2)
.closeArray()
.array()
.object()
.stringValue("foo", "Foo")
.closeObject()
.closeArray()
newJsonArray((rootArray) -> {
rootArray.array((a) -> a.stringValue("a1").stringValue("a2"));
rootArray.array((a) -> a.numberValue(1).numberValue(2));
rootArray.array((a) -> a.object((o) -> o.stringValue("foo", "Foo"));
}).build()