Pact consumer client library in Swift
Swift Ruby Other
Latest commit 4ef5fcc Dec 26, 2016 @giginet giginet Upgrade SwiftLint to 0.15


Build Status Language Carthage compatible

Pact consumer client library in Swift

Phakchi provides a DSL in Swift for creating pact files.

See the Pact README for detail.



Add the following line to your Cartfile.private.

github "cookpad/Phakchi"

For information on how to use Carthage, please refer to the official Carthage documentation.


Add this statements to your Podfile.

target 'YourApplicationTests' do
    pod 'Phakchi'

For information on how to use CocoaPods, please refer to the official CocoaPods documentation.



Before you write your Pact definitions, you have to configure the mock server.

First, add a Gemfile to your project's root directory.

source ""

gem "pact-mock_service"

Then, edit your test scheme and add the following to the Pre-actions section. (You might have to make changes to the PATH setting.)

BUNDLE_GEMFILE="$SRCROOT"/Gemfile bundle exec "$SRCROOT"/Carthage/Checkouts/Phakchi/scripts/

And set Provide build settings from to your test target.

In the same way, you should run the stop_control_server script post testing.

BUNDLE_GEMFILE="$SRCROOT"/Gemfile bundle exec "$SRCROOT"/Carthage/Checkouts/Phakchi/scripts/

Describe contracts using XCTest

First, Phakchi connects to the control server. The control server is able to launch mock servers. Launched mock servers are represented as instances of Session.

Then you need to describe the interactions you are going to have with the mock server. Once the interactions are described, you then send a request to the mock server, check that the response is correct, and if your validation passes, a Pact file will be generated.

Below you will find an example for writing contracts for an API to fetch recipes with XCTest. The request to the API is done by RecipeClient's fetchRecipes(keyword) method.

import XCTest
import Phakchi

class SamplePact: XCTestCase {
    let controlServer: ControlServer = ControlServer.default
    var session: Session!

    override func setUp() {

        // Launch a mock server
        let expectationToStart = expectation(description: "session was started")
        controlServer.startSession(consumerName: "consumer", providerName: "provider") { session in
            self.session = session
        waitForExpectations(timeout: 5.0, handler: nil)

    func testFetchRecipes() {
        XCTAssertEqual(controlServer.sessions.count, 1)
        let expectationToRun = expectation(description: "contract is valid")
        session.given("There are 2 recipes")
            .uponReceiving("a request for recipe")
            .willRespondWith(status: 200, body: Matcher.eachLike(["recipes": ["name": "Tuna", "description": "Delicious"]], min: 10)) { isValid in
            // This block will be executed after completion
        }, executionBlock: { completeTest in
            RecipeClient.fetchRecipes(from: "Sushi") { (recipes, error) in
                // Expected to return 10 Sushi objects
                XCTAssertEqual(recipes.count, 10)
                XCTAssertEqual(recipes[0].name, "Tuna")
                XCTAssertEqual(recipes[0].description, "Delicious")
                completeTest() // Tell completion to the mock server
        waitForExpectations(timeout: 5.0, handler: nil)

    override func tearDown() {
        let expectationToClean = expectation(description: "Tear down Pact environment")
        // Clean up all interactions on mock server
        session.clean {
        waitForExpectations(timeout: 5.0, handler: nil)



If you get the error below when trying to launch mock servers, you should set Allow Arbitrary Loads to YES in the Info.plist of your application target.

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.


As described in the above example code, you can use helpers to match using regular expressions.

You can have a look at this documentation for more details.


  • iOS 8+
  • Swift 3.0.1
  • Xcode 8.1+