pact-mock_service 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +38 -10
- data/lib/pact/consumer_contract/consumer_contract_writer.rb +1 -1
- data/lib/pact/mock_service/app.rb +3 -3
- data/lib/pact/mock_service/cli.rb +9 -9
- data/lib/pact/mock_service/request_handlers/interaction_replay.rb +28 -4
- data/lib/pact/mock_service/request_handlers.rb +1 -1
- data/lib/pact/mock_service/version.rb +1 -1
- data/lib/pact/stub_service/cli.rb +10 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19d534d5cb2a38d99b0cb36e8f4c373e7452d708
|
4
|
+
data.tar.gz: 4bcd7d9c3438fdd76aaed92ac9823946285d5789
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 182e56ac2b5e437f4d5014e6c4e816a4a7f90d338243d90471fcbe6c9222cf60c76511bcada3766850c58989587fe860698722c00054e5a2f57a6d191c4e975a
|
7
|
+
data.tar.gz: 918ebb1400b5b9180f2a28b49ae9cd032b6209c22ad1b35b5746c8fd70c8a0066c3f777a9daba9dc0dbfdf6043622228eaee9d53a066d7d3ec5e389c968ad221
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,9 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
git log --pretty=format:' * %h - %s (%an, %ad)' vX.Y.Z..HEAD
|
4
4
|
|
5
|
+
### 2.5.0 (2017-10-28)
|
6
|
+
* bc15e21 - feat(pact-stub-service): handle case where multiple responses match (Beth Skurrie, Sat Oct 28 09:15:55 2017 +1100)
|
7
|
+
|
5
8
|
### 2.4.0 (2017-10-13)
|
6
9
|
* 56bd683 - feat(stub): add pact-stub-service CLI (Beth Skurrie, Fri Oct 13 08:20:49 2017 +1100)
|
7
10
|
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
|
2
|
-
# Pact Mock Service
|
2
|
+
# Pact Mock and Stub Service
|
3
3
|
|
4
4
|
[![Build Status](https://travis-ci.org/pact-foundation/pact-mock_service.svg?branch=master)](https://travis-ci.org/pact-foundation/pact-mock_service)
|
5
5
|
|
6
|
-
This codebase provides the HTTP mock service used by implementations of [Pact][pact]. It is packaged as a gem, and as a standalone executable for Mac OSX and Linux and Windows.
|
6
|
+
This codebase provides the HTTP mock and stub service used by implementations of [Pact][pact]. It is packaged as a gem, and as a standalone executable for Mac OSX and Linux and Windows.
|
7
7
|
|
8
8
|
The mock service provides the following endpoints:
|
9
9
|
|
@@ -40,15 +40,15 @@ Or add `gem "pact-mock_service"` to your Gemfile then run:
|
|
40
40
|
|
41
41
|
Run `pact-mock-service help` for command line options.
|
42
42
|
|
43
|
-
## Usage
|
43
|
+
## Mock Service Usage
|
44
44
|
|
45
|
-
The lifecycle of the a mock service instance during at test suite is as follows:
|
45
|
+
Each mock service process is designed to mock only ONE provider. To mock multiple providers, you will need to start a process for each provider. The lifecycle of the a mock service instance during at test suite is as follows:
|
46
46
|
|
47
|
-
_Before suite:_ start mock service
|
48
|
-
_Before each test:_ clear interactions from previous test
|
49
|
-
_During test:_ set up interactions, execute interactions
|
50
|
-
_After each test:_ verify interactions
|
51
|
-
_After suite:_ write pact file, stop mock service
|
47
|
+
* _Before suite:_ start mock service
|
48
|
+
* _Before each test:_ clear interactions from previous test
|
49
|
+
* _During test:_ set up interactions, execute interactions
|
50
|
+
* _After each test:_ verify interactions
|
51
|
+
* _After suite:_ write pact file, stop mock service
|
52
52
|
|
53
53
|
Each mock service instance can only handle one test process/thread at a time. If you wish to run multiple test threads in parallel, you will need to start each mock service instance on a different port, and set the `--pact-file-write-mode` to `merge` (see usage notes below).
|
54
54
|
|
@@ -73,7 +73,7 @@ Options:
|
|
73
73
|
[--sslcert=SSLCERT] # Specify the path to the SSL cert to use when running the service over HTTPS
|
74
74
|
[--sslkey=SSLKEY] # Specify the path to the SSL key to use when running the service over HTTPS
|
75
75
|
|
76
|
-
Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown.
|
76
|
+
Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT).
|
77
77
|
```
|
78
78
|
|
79
79
|
See [script/example.sh](script/example.sh) for an executable example.
|
@@ -94,6 +94,34 @@ If you need to provide your own certificate and key, use the following syntax.
|
|
94
94
|
|
95
95
|
Read the wiki page on [CORS][cors].
|
96
96
|
|
97
|
+
## Stub Service Usage
|
98
|
+
|
99
|
+
The pact-stub-service allows you to reuse interactions that have been generated in previous tests. The typical situation would be to generate your pact file using unit tests, and then use the pact stub service for your higher level integration/ui tests. To help reduce the number of interactions that need verifying, you will want to use flexible matching on both requests and responses.
|
100
|
+
|
101
|
+
Unlike the mock service, which has a Ruby DSL for managing its lifecycle, the mock service can currently only be started from the command line, so you will need to start/background/kill the process yourself. If this is causing problems, please raise it in the pact-dev google group and we can discuss potential enhancements.
|
102
|
+
|
103
|
+
```
|
104
|
+
Usage:
|
105
|
+
pact-stub-service PACT ...
|
106
|
+
|
107
|
+
Options:
|
108
|
+
-p, [--port=PORT] # Port on which to run the service
|
109
|
+
-h, [--host=HOST] # Host on which to bind the service
|
110
|
+
# Default: localhost
|
111
|
+
-l, [--log=LOG] # File to which to log output
|
112
|
+
-o, [--cors=CORS] # Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses
|
113
|
+
[--ssl], [--no-ssl] # Use a self-signed SSL cert to run the service over HTTPS
|
114
|
+
[--sslcert=SSLCERT] # Specify the path to the SSL cert to use when running the service over HTTPS
|
115
|
+
[--sslkey=SSLKEY] # Specify the path to the SSL key to use when running the service over HTTPS
|
116
|
+
|
117
|
+
Description:
|
118
|
+
Start a stub service with the given pact file(s). Where multiple matching interactions are found, the
|
119
|
+
interactions will be sorted by response status, and the first one will be returned. This may lead to some
|
120
|
+
non-deterministic behaviour. If you are having problems with this, please raise it on the pact-dev google
|
121
|
+
group, and we can discuss some potential enhancements. Note that only versions 1 and 2 of the pact
|
122
|
+
specification are currently supported.
|
123
|
+
```
|
124
|
+
|
97
125
|
## Contributing
|
98
126
|
|
99
127
|
See [CONTRIBUTING.md](/CONTRIBUTING.md)
|
@@ -20,7 +20,7 @@ module Pact
|
|
20
20
|
logger = Logger.from_options(options)
|
21
21
|
@name = options.fetch(:name, "MockService")
|
22
22
|
@session = Session.new(options.merge(logger: logger))
|
23
|
-
setup_stub(options[:stub_pactfile_paths]) if options[:stub_pactfile_paths]
|
23
|
+
setup_stub(options[:stub_pactfile_paths]) if options[:stub_pactfile_paths]
|
24
24
|
request_handlers = RequestHandlers.new(@name, logger, @session, options)
|
25
25
|
@app = Rack::Builder.app do
|
26
26
|
use Pact::Consumer::MockService::ErrorHandler, logger
|
@@ -39,7 +39,7 @@ module Pact
|
|
39
39
|
|
40
40
|
def setup_stub stub_pactfile_paths
|
41
41
|
stub_pactfile_paths.each do | pactfile_path |
|
42
|
-
$stdout.puts "Loading interactions from #{pactfile_path}"
|
42
|
+
$stdout.puts "INFO: Loading interactions from #{pactfile_path}"
|
43
43
|
hash_interactions = JSON.parse(File.read(pactfile_path))['interactions']
|
44
44
|
interactions = hash_interactions.collect { | hash | Interaction.from_hash(hash) }
|
45
45
|
@session.set_expected_interactions interactions
|
@@ -49,7 +49,7 @@ module Pact
|
|
49
49
|
def write_pact_if_configured
|
50
50
|
consumer_contract_writer = ConsumerContractWriter.new(@session.consumer_contract_details, StdoutLogger.new)
|
51
51
|
if consumer_contract_writer.can_write? && !@session.pact_written?
|
52
|
-
$stdout.puts "Writing pact before shutting down"
|
52
|
+
$stdout.puts "INFO: Writing pact before shutting down"
|
53
53
|
consumer_contract_writer.write
|
54
54
|
end
|
55
55
|
end
|
@@ -13,14 +13,14 @@ module Pact
|
|
13
13
|
PACT_FILE_WRITE_MODE_DESC = "`overwrite` or `merge`. Use `merge` when running multiple mock service instances in parallel for the same consumer/provider pair." +
|
14
14
|
" Ensure the pact file is deleted before running tests when using this option so that interactions deleted from the code are not maintained in the file."
|
15
15
|
|
16
|
-
desc 'service', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown."
|
16
|
+
desc 'service', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
17
17
|
method_option :consumer, desc: "Consumer name"
|
18
18
|
method_option :provider, desc: "Provider name"
|
19
19
|
method_option :port, aliases: "-p", desc: "Port on which to run the service"
|
20
20
|
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
21
21
|
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
22
22
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
23
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
23
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
24
24
|
method_option :log, aliases: "-l", desc: "File to which to log output"
|
25
25
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
26
26
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
@@ -38,7 +38,7 @@ module Pact
|
|
38
38
|
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
39
39
|
method_option :log_dir, aliases: "-l", desc: "File to which to log output"
|
40
40
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
41
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
41
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
42
42
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
43
43
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
44
44
|
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
@@ -49,7 +49,7 @@ module Pact
|
|
49
49
|
ControlServer::Run.(options)
|
50
50
|
end
|
51
51
|
|
52
|
-
desc 'start', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown."
|
52
|
+
desc 'start', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
53
53
|
method_option :consumer, desc: "Consumer name"
|
54
54
|
method_option :provider, desc: "Provider name"
|
55
55
|
method_option :port, aliases: "-p", default: '1234', desc: "Port on which to run the service"
|
@@ -58,7 +58,7 @@ module Pact
|
|
58
58
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
59
59
|
method_option :pid_dir, desc: "PID dir", default: 'tmp/pids'
|
60
60
|
method_option :log, aliases: "-l", desc: "File to which to log output"
|
61
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
61
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
62
62
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
63
63
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
64
64
|
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
@@ -78,7 +78,7 @@ module Pact
|
|
78
78
|
mock_service_pidfile.kill_process
|
79
79
|
end
|
80
80
|
|
81
|
-
desc 'restart', "Start or restart a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown."
|
81
|
+
desc 'restart', "Start or restart a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
82
82
|
method_option :consumer, desc: "Consumer name"
|
83
83
|
method_option :provider, desc: "Provider name"
|
84
84
|
method_option :port, aliases: "-p", default: '1234', desc: "Port on which to run the service"
|
@@ -87,7 +87,7 @@ module Pact
|
|
87
87
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
88
88
|
method_option :pid_dir, desc: "PID dir", default: 'tmp/pids'
|
89
89
|
method_option :log, aliases: "-l", desc: "File to which to log output"
|
90
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
90
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
91
91
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
92
92
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
93
93
|
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
@@ -103,7 +103,7 @@ module Pact
|
|
103
103
|
method_option :port, aliases: "-p", desc: "Port on which to run the service", default: '1234'
|
104
104
|
method_option :log_dir, aliases: "-l", desc: "File to which to log output", default: "log"
|
105
105
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
106
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
106
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '2'
|
107
107
|
method_option :pid_dir, desc: "PID dir", default: "tmp/pids"
|
108
108
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
109
109
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
@@ -130,7 +130,7 @@ module Pact
|
|
130
130
|
method_option :log_dir, aliases: "-l", desc: "File to which to log output", default: "log"
|
131
131
|
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written", default: "."
|
132
132
|
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
133
|
-
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '
|
133
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
134
134
|
method_option :pid_dir, desc: "PID dir", default: "tmp/pids"
|
135
135
|
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
136
136
|
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
@@ -21,15 +21,16 @@ module Pact
|
|
21
21
|
include Pact::Matchers
|
22
22
|
include PrettyGenerate
|
23
23
|
|
24
|
-
attr_accessor :name, :logger, :expected_interactions, :actual_interactions, :verified_interactions
|
24
|
+
attr_accessor :name, :logger, :expected_interactions, :actual_interactions, :verified_interactions, :multiple_interactions_handler
|
25
25
|
|
26
|
-
def initialize name, logger, session, cors_enabled=false
|
26
|
+
def initialize name, logger, session, cors_enabled = false, stub = false
|
27
27
|
@name = name
|
28
28
|
@logger = logger
|
29
29
|
@expected_interactions = session.expected_interactions
|
30
30
|
@actual_interactions = session.actual_interactions
|
31
31
|
@verified_interactions = session.verified_interactions
|
32
32
|
@cors_enabled = cors_enabled
|
33
|
+
@multiple_interactions_handler = stub ? HandleMultipleInteractionsFoundForStub : HandleMultipleInteractionsFound
|
33
34
|
end
|
34
35
|
|
35
36
|
def match? env
|
@@ -62,7 +63,7 @@ module Pact
|
|
62
63
|
end
|
63
64
|
|
64
65
|
def handle_more_than_one_matching_interaction actual_request, matching_interactions
|
65
|
-
|
66
|
+
multiple_interactions_handler.call(actual_request, matching_interactions, verified_interactions, actual_interactions, logger)
|
66
67
|
end
|
67
68
|
|
68
69
|
def handle_unrecognised_request actual_request, candidate_interactions
|
@@ -79,7 +80,7 @@ module Pact
|
|
79
80
|
|
80
81
|
extend PrettyGenerate
|
81
82
|
|
82
|
-
def self.call actual_request, matching_interactions, logger
|
83
|
+
def self.call actual_request, matching_interactions, verified_interactions, actual_interactions, logger
|
83
84
|
logger.error "Multiple interactions found for #{actual_request.method_and_path}:"
|
84
85
|
matching_interactions.each do | interaction |
|
85
86
|
logger.debug pretty_generate(Pact::MockService::InteractionDecorator.new(interaction))
|
@@ -103,6 +104,29 @@ module Pact
|
|
103
104
|
end
|
104
105
|
end
|
105
106
|
|
107
|
+
class HandleMultipleInteractionsFoundForStub
|
108
|
+
|
109
|
+
extend PrettyGenerate
|
110
|
+
|
111
|
+
def self.call actual_request, matching_interactions, verified_interactions, actual_interactions, logger
|
112
|
+
logger.warn "Multiple interactions found for #{actual_request.method_and_path}:"
|
113
|
+
matching_interactions.each do | interaction |
|
114
|
+
logger.debug pretty_generate(Pact::MockService::InteractionDecorator.new(interaction))
|
115
|
+
end
|
116
|
+
response actual_request, matching_interactions, verified_interactions, actual_interactions, logger
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.response actual_request, matching_interactions, verified_interactions, actual_interactions, logger
|
120
|
+
logger.warn "Sorting responses by response status and returning first."
|
121
|
+
interaction = first_most_successful_interaction(matching_interactions)
|
122
|
+
HandleMatchedInteraction.call(interaction, verified_interactions, actual_interactions, logger)
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.first_most_successful_interaction matching_interactions
|
126
|
+
matching_interactions.sort{ |i1, i2| Pact::Reification.from_term(i1.response.status) <=> Pact::Reification.from_term(i2.response.status) }.first
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
106
130
|
class HandleUnrecognisedInteraction
|
107
131
|
|
108
132
|
def self.call actual_request, candidate_interactions, actual_interactions, logger
|
@@ -33,7 +33,7 @@ module Pact
|
|
33
33
|
LogGet.new(name, logger),
|
34
34
|
PactPost.new(name, logger, session),
|
35
35
|
IndexGet.new(name, logger),
|
36
|
-
InteractionReplay.new(name, logger, session, options[:cors_enabled])
|
36
|
+
InteractionReplay.new(name, logger, session, options[:cors_enabled], options[:stub_pactfile_paths])
|
37
37
|
]
|
38
38
|
end
|
39
39
|
end
|
@@ -10,7 +10,16 @@ module Pact
|
|
10
10
|
module StubService
|
11
11
|
class CLI < Pact::MockService::CLI::CustomThor
|
12
12
|
|
13
|
-
desc 'PACT ...', "Start a stub service with the given pact file(s).
|
13
|
+
desc 'PACT ...', "Start a stub service with the given pact file(s)."
|
14
|
+
long_desc <<-DOC
|
15
|
+
Start a stub service with the given pact file(s).
|
16
|
+
Where multiple matching interactions are found, the interactions will be sorted by
|
17
|
+
response status, and the first one will be returned. This may lead to some non-deterministic
|
18
|
+
behaviour. If you are having problems with this, please raise it on the pact-dev google group,
|
19
|
+
and we can discuss some potential enhancements.
|
20
|
+
Note that only versions 1 and 2 of the pact specification are currently supported.
|
21
|
+
DOC
|
22
|
+
|
14
23
|
|
15
24
|
method_option :port, aliases: "-p", desc: "Port on which to run the service"
|
16
25
|
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact-mock_service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Fraser
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2017-10-
|
15
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rack
|