This library provides a Swift / Objective C DSL for creating Consumer Pacts.
Implements Pact Specification v2, including flexible matching.
This DSL relies on the Ruby pact-mock_service gem to provide the mock service for the tests.
Note: see Upgrading for notes on upgrading from 0.2 to 0.3
Install the pact-mock_service
gem install pact-mock_service -v 0.9.0
Using Carthage library manager
- See the PactSwiftExample for an example project using the library with Carthage.
- See the PactObjectiveCExample for an example project using the library with CocoaPods.
Write a Unit test similar to the following (NB: this example is using the Quick test framework)
import PactConsumerSwift
...
beforeEach {
animalMockService = MockService(provider: "Animal Service", consumer: "Animal Consumer Swift")
animalServiceClient = AnimalServiceClient(baseUrl: animalMockService!.baseUrl)
}
it("gets an alligator") {
animalMockService!.given("an alligator exists")
.uponReceiving("a request for an alligator")
.withRequest(method:.GET, path: "/alligator")
.willRespondWith(status:200,
headers: ["Content-Type": "application/json"],
body: ["name": "Mary"])
//Run the tests
animalMockService!.run { (testComplete) -> Void in
animalServiceClient!.getAlligator { (alligator) in
expect(alligator.name).to(equal("Mary"))
testComplete()
}
}
}
Write a Unit test similar to the following
@import PactConsumerSwift;
...
- (void)setUp {
[super setUp];
self.animalMockService = [[MockService alloc] initWithProvider:@"Animal Provider"
consumer:@"Animal Service Client Objective-C"];
self.animalServiceClient = [[OCAnimalServiceClient alloc] initWithBaseUrl:self.animalMockService.baseUrl];
}
- (void)testGetAlligator {
typedef void (^CompleteBlock)();
[[[[self.animalMockService given:@"an alligator exists"]
uponReceiving:@"oc a request for an alligator"]
withRequestHTTPMethod:PactHTTPMethodGET
path:@"/alligator"
query:nil headers:nil body:nil]
willRespondWithHTTPStatus:200
headers:@{@"Content-Type": @"application/json"}
body: @"{ \"name\": \"Mary\"}" ];
[self.animalMockService run:^(CompleteBlock testComplete) {
Animal *animal = [self.animalServiceClient getAlligator];
XCTAssertEqualObjects(animal.name, @"Mary");
testComplete();
}];
}
In addition to verbatim value matching, you have 3 useful matching functions
in the Matcher
class that can increase expressiveness and reduce brittle test
cases.
Matcher.term(matcher, generate)
- tells Pact that the value should match using a given regular expression, usinggenerate
in mock responses.generate
must be a string.Matcher.somethingLike(content)
- tells Pact that the value itself is not important, as long as the element type (valid JSON number, string, object etc.) itself matches.Matcher.eachLike(content, min)
- tells Pact that the value should be an array type, consisting of elements like those passed in.min
must be >= 1.content
may be a valid JSON value: e.g. strings, numbers and objects.
NOTE: One caveat to note, is that you will need to use valid Ruby regular expressions and double escape backslashes.
See the PactSpecs.swift
, PactObjectiveCTests.m
for examples on how to expect error responses, how to use query params, and the Matchers.
For more on request / response matching, see Matching.
If your setup is correct and your tests run against the pack mock server, then you should see a log file here:
$YOUR_PROJECT/tmp/pact.log
And the generated pacts, here:
$YOUR_PROJECT/tmp/pacts/...
See Verifying pacts for more information.
For an end to end example with a ruby back end service, have a look at the KatKit example. Here is an article using a dockerized nodejs service which uses provider states.
- The Pact website Pact
- The pact mock server that the Swift library uses under the hood Pact mock service
- A pact broker for managing the generated pact files (so you don't have to manually copy them around!) Pact broker
Please read CONTRIBUTING.md