This library is an Elixir wrapper for the pact-reference implementation
And it is in PRE alpha shape without any semantic versioning or documentation.
It is not yet usable as many needed parts like publishing a pact file to a broker or pact verification on the provider side are still missing. Also there is no documentation available, yet.
You need Rust in order to build and install the package.
If available in Hex, the package can be installed
by adding pact_elixir
to your list of dependencies in mix.exs
:
def deps do
[
{:pact_elixir, "~> 0.5.0"}
]
end
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/pact_elixir.
This is an example test case:
defmodule PactElixir.PactMockServerTest do
use ExUnit.Case
alias PactElixir.{PactMockServer, ServiceProvider}
import PactElixir.Dsl
setup do
options = %{provider: "SomeProvider", consumer: "SomeConsumer"}
provider = new_service_provider(options)
{:ok, mock_server_pid} = start_supervised({PactMockServer, provider})
{:ok, mock_server_pid: mock_server_pid, provider: provider}
end
describe "SomeProvider talks to SomeConsumer" do
test "some basic test", %{mock_server_pid: mock_server_pid} do
expected = "{groups: ['Editors'], id: 123, username: 'UserA'}"
user(mock_server_pid)
assert expected == user(mock_server_pid).body
assert {:ok} == PactMockServer.write_pact_file(mock_server_pid)
end
end
defp get_request(path, mock_server_pid) when is_pid(mock_server_pid) do
get_request(path, PactMockServer.port(mock_server_pid))
end
defp get_request(path, port) when is_number(port) do
%HTTPoison.Response{} = HTTPoison.get!("http://localhost:#{port}#{path}")
end
def user(mock_server_pid) do
get_request("/users/UserA", mock_server_pid)
end
defp new_service_provider(options \\ %{}) do
options
|> PactElixir.Dsl.service_provider()
|> add_interaction(
"give me foo",
given("UserA exists and is not an administrator"),
with_request(method: :get, path: "/users/UserA"),
will_respond_with(status: 200, body: "{groups: ['Editors'], id: 123, username: 'UserA'}")
)
end
end
You should be able to run it with mix test <path_to_test_case>
.
Publishing
If the test passes, a json file will be created and saved in a new directory - ./pacts
.
Currently, pact publishing is not yet implemented in this library. You can run the following bash script for your basic publishing needs:
#!/bin/bash
# This script:
# 1) extracts the name of provider and consumer from the name of a JSON pact file
# e.g.: Consumer1-Provider.json gives you consumer Consumer1 and provider Provider
# 2) reads the JSON pact file from /pacts directory (pacts are stored there by specification)
# 3) publishes pact to Pact Broker
for pact in ./pacts/*.json; do
pact_name=$(basename $pact)
consumer=${pact_name%-*}
provider=${pact_name#*-}
provider=${provider%.*}
curl -v -XPUT \-H "Content-Type: application/json" \
-d@${pact} \
https://<your-pact-broker-url>/pacts/provider/$provider/consumer/$consumer/version/<some-version-number>
done
Compiling NIF crate :pactmockserver (native/pactmockserver)...
could not compile dependency :pact_elixir, "mix compile"
failed. You can recompile this dependency with "mix deps.compile pact_elixir", update it with "mix deps.update pact_elixir" or clean it with "mix deps.clean pact_elixir"
This can be solved by ensuring proper structure of mix.exs
.
- Ensure you have
rustler
listed in compilers - Ensure
pactmockserver
is listed in rustler_crates
def project do
[
#...
compilers: [:phoenix, :rustler] ++ Mix.compilers(),
rustler_crates: rustler_crates(Mix.env()),
#...
]
end
(This is an example setting, where you don't want to ship any rustler crates to production. Bottom line is, there has to be a function that returns the crates list, including pactmockserver).
defp rustler_crates(mix_env) when mix_env in [:test, :dev] do
[
pactmockserver: [
path: "deps/pact_elixir/native/pactmockserver",
mode: (:debug),
]
]
end
defp rustler_crates(_prod) do
[]
end
Properly installing Rust should solve a majority of the problems. Just add the following code (this is for a Debian distro, it assumes you have curl installed):
# Rust is required by pact-elixir
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH=$HOME/.cargo/bin:$PATH