http_stub 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/http/stub/registry.rb +23 -0
- data/lib/http/stub/server.rb +11 -15
- data/lib/http/stub/stub.rb +32 -0
- data/lib/http/stub/version.rb +1 -1
- data/lib/http_stub.rb +3 -0
- data/spec/lib/http/client_integration_spec.rb +1 -3
- data/spec/lib/http/rake_task_integration_spec.rb +1 -1
- data/spec/lib/http/registry_spec.rb +79 -0
- data/spec/lib/http/server_spec.rb +41 -32
- data/spec/lib/http/stub_spec.rb +157 -0
- metadata +25 -3
@@ -0,0 +1,23 @@
|
|
1
|
+
module Http
|
2
|
+
module Stub
|
3
|
+
|
4
|
+
class Registry
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@stubs = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(stub, request)
|
11
|
+
@stubs.unshift(stub)
|
12
|
+
request.logger.info "Stub registered: #{stub}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_for(request)
|
16
|
+
request.logger.info "Finding stub fulfilling: #{request}"
|
17
|
+
@stubs.find { |stub| stub.stubs?(request) }
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/http/stub/server.rb
CHANGED
@@ -3,17 +3,17 @@ module Http
|
|
3
3
|
|
4
4
|
class Server < ::Sinatra::Base
|
5
5
|
|
6
|
-
SUPPORTED_REQUEST_TYPES = [:get, :post, :put, :delete, :patch, :options].freeze
|
7
|
-
|
8
6
|
enable :dump_errors, :logging
|
9
7
|
|
10
|
-
def initialize
|
8
|
+
def initialize
|
11
9
|
super()
|
12
|
-
@
|
10
|
+
@registry = Http::Stub::Registry.new
|
13
11
|
end
|
14
12
|
|
15
13
|
private
|
16
14
|
|
15
|
+
SUPPORTED_REQUEST_TYPES = [:get, :post, :put, :delete, :patch, :options].freeze
|
16
|
+
|
17
17
|
def self.any_request_type(path, opts={}, &block)
|
18
18
|
SUPPORTED_REQUEST_TYPES.each { |type| self.send(type, path, opts, &block) }
|
19
19
|
end
|
@@ -24,15 +24,17 @@ module Http
|
|
24
24
|
# {
|
25
25
|
# "uri": "/some/path",
|
26
26
|
# "method": "get",
|
27
|
+
# "parameters": {
|
28
|
+
# "key": "value",
|
29
|
+
# ...
|
30
|
+
# },
|
27
31
|
# "response": {
|
28
32
|
# "status": "200",
|
29
33
|
# "body": "Hello World"
|
30
34
|
# }
|
31
35
|
# }
|
32
36
|
post "/stub" do
|
33
|
-
|
34
|
-
logger.info "Stub registered: #{data}"
|
35
|
-
@response_register[data["uri"]] = data
|
37
|
+
@registry.add(Http::Stub::Stub.new(request), request)
|
36
38
|
halt 200
|
37
39
|
end
|
38
40
|
|
@@ -41,14 +43,8 @@ module Http
|
|
41
43
|
private
|
42
44
|
|
43
45
|
def handle_stub_request
|
44
|
-
|
45
|
-
|
46
|
-
if stub_data && stub_data["method"].downcase == request.request_method.downcase
|
47
|
-
response_data = stub_data["response"]
|
48
|
-
halt response_data["status"].to_i, response_data["body"]
|
49
|
-
else
|
50
|
-
halt 404
|
51
|
-
end
|
46
|
+
stub = @registry.find_for(request)
|
47
|
+
stub ? halt(stub.response.status, stub.response.body) : halt(404)
|
52
48
|
end
|
53
49
|
|
54
50
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Http
|
2
|
+
module Stub
|
3
|
+
class Stub
|
4
|
+
|
5
|
+
Response = ImmutableStruct.new(:status, :body)
|
6
|
+
|
7
|
+
attr_reader :response
|
8
|
+
|
9
|
+
def initialize(request)
|
10
|
+
@data = JSON.parse(request.body.read)
|
11
|
+
@response = Response.new(status: @data["response"]["status"], body: @data["response"]["body"])
|
12
|
+
end
|
13
|
+
|
14
|
+
def stubs?(request)
|
15
|
+
@data["uri"] == request.path_info &&
|
16
|
+
@data["method"].downcase == request.request_method.downcase &&
|
17
|
+
parameters == request.params
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
@data.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def parameters
|
27
|
+
@data["parameters"] || {}
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/http/stub/version.rb
CHANGED
data/lib/http_stub.rb
CHANGED
@@ -3,8 +3,11 @@ require 'bundler/setup'
|
|
3
3
|
Bundler.require(:default)
|
4
4
|
|
5
5
|
require 'sinatra'
|
6
|
+
require 'immutable_struct'
|
6
7
|
require 'net/http'
|
7
8
|
require 'json'
|
8
9
|
|
10
|
+
require File.expand_path('../http/stub/stub', __FILE__)
|
11
|
+
require File.expand_path('../http/stub/registry', __FILE__)
|
9
12
|
require File.expand_path('../http/stub/server', __FILE__)
|
10
13
|
require File.expand_path('../http/stub/client', __FILE__)
|
@@ -12,9 +12,7 @@ describe Http::Stub::Client do
|
|
12
12
|
|
13
13
|
describe "when a response for a request is stubbed" do
|
14
14
|
|
15
|
-
before(:each)
|
16
|
-
client.stub_response!("/a_path", method: :get, status: 200, body: "Some body")
|
17
|
-
end
|
15
|
+
before(:each) { client.stub_response!("/a_path", method: :get, status: 200, body: "Some body") }
|
18
16
|
|
19
17
|
describe "and that request is made" do
|
20
18
|
|
@@ -5,7 +5,7 @@ describe Http::Stub::RakeTask do
|
|
5
5
|
|
6
6
|
it "should start a stub server that responds to stub requests" do
|
7
7
|
request = Net::HTTP::Post.new("/stub")
|
8
|
-
request.body = "{}
|
8
|
+
request.body = { "response" => { "status" => 302, "body" => "Some Body" } }.to_json
|
9
9
|
|
10
10
|
response = Net::HTTP.new("localhost", 8001).start { |http| http.request(request) }
|
11
11
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
describe Http::Stub::Registry do
|
2
|
+
|
3
|
+
let(:registry) { Http::Stub::Registry.new }
|
4
|
+
|
5
|
+
let(:logger) { double("Logger").as_null_object }
|
6
|
+
let(:request) { double("HttpRequest", logger: logger, to_s: "Request as String") }
|
7
|
+
|
8
|
+
describe "#add" do
|
9
|
+
|
10
|
+
it "should log that the stub has been registered" do
|
11
|
+
stub = double(Http::Stub::Stub, to_s: "Stub as String")
|
12
|
+
logger.should_receive(:info).with(/Stub as String/)
|
13
|
+
|
14
|
+
registry.add(stub, request)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#find_for" do
|
20
|
+
|
21
|
+
describe "when multiple stubs have been registered" do
|
22
|
+
|
23
|
+
let(:stubs) do
|
24
|
+
(1..3).map { |i| double("#{Http::Stub::Stub}#{i}", :stubs? => false) }
|
25
|
+
end
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
stubs.each { |stub| registry.add(stub, request) }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "and one registered stub matches the request" do
|
32
|
+
|
33
|
+
before(:each) { stubs[1].stub!(:stubs?).and_return(true) }
|
34
|
+
|
35
|
+
it "should return the stub" do
|
36
|
+
registry.find_for(request).should eql(stubs[1])
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "and multiple registered stubs match the request" do
|
42
|
+
|
43
|
+
before(:each) do
|
44
|
+
[0, 2].each { |i| stubs[i].stub!(:stubs?).and_return(true) }
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should support stub overrides by returning the last stub registered" do
|
48
|
+
registry.find_for(request).should eql(stubs[2])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "and no registered stubs match the request" do
|
54
|
+
|
55
|
+
it "should return nil" do
|
56
|
+
registry.find_for(request).should be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "when no stub has been registered" do
|
64
|
+
|
65
|
+
it "should return nil" do
|
66
|
+
registry.find_for(request).should be_nil
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
it "it should log that a stub is being found" do
|
72
|
+
logger.should_receive(:info).with(/Request as String/)
|
73
|
+
|
74
|
+
registry.find_for(request)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -1,65 +1,74 @@
|
|
1
1
|
describe Http::Stub::Server do
|
2
2
|
include Rack::Test::Methods
|
3
3
|
|
4
|
-
let(:app) { Http::Stub::Server }
|
4
|
+
let(:app) { Http::Stub::Server.new }
|
5
|
+
|
6
|
+
let(:registry) { double(Http::Stub::Registry).as_null_object }
|
7
|
+
before(:each) { Http::Stub::Registry.stub!(:new).and_return(registry) }
|
8
|
+
|
5
9
|
let(:response) { last_response }
|
6
10
|
let(:response_body) { response.body.to_s }
|
7
11
|
|
8
|
-
|
12
|
+
describe "when a stub request is received" do
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
it "should register a stub encapsulating the request" do
|
15
|
+
stub = double(Http::Stub::Stub)
|
16
|
+
Http::Stub::Stub.should_receive(:new).and_return(stub)
|
17
|
+
registry.should_receive(:add).with(stub, anything)
|
13
18
|
|
14
|
-
|
15
|
-
post "/stub", '{"uri": "' + test_url + '", "method": "' + request_type.to_s + '", "response": {"status":"200", "body":"Foo"}}'
|
19
|
+
issue_stub_request
|
16
20
|
end
|
17
21
|
|
18
|
-
|
22
|
+
end
|
19
23
|
|
20
|
-
|
24
|
+
describe "when a playback request is received" do
|
21
25
|
|
22
|
-
|
23
|
-
response.status.should eql(200)
|
24
|
-
end
|
26
|
+
describe "and the request has been stubbed" do
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
before(:each) do
|
29
|
+
registry.stub!(:find_for).and_return(
|
30
|
+
double(Http::Stub::Stub, response: double("StubResponse", status: 500, body: "Some text")))
|
28
31
|
end
|
29
32
|
|
30
|
-
|
33
|
+
it "should respond with the configured status" do
|
34
|
+
get "/a_path"
|
31
35
|
|
32
|
-
|
36
|
+
response.status.should eql(500)
|
37
|
+
end
|
33
38
|
|
34
|
-
|
39
|
+
it "should respond with the configured body" do
|
40
|
+
get "/a_path"
|
35
41
|
|
36
|
-
|
37
|
-
response.status.should eql(404)
|
42
|
+
response_body.should eql("Some text")
|
38
43
|
end
|
39
44
|
|
40
45
|
end
|
41
46
|
|
42
|
-
|
47
|
+
describe "and the request has not been stubbed" do
|
43
48
|
|
44
|
-
|
45
|
-
|
49
|
+
before(:each) do
|
50
|
+
registry.stub!(:find_for).and_return(nil)
|
51
|
+
end
|
46
52
|
|
47
|
-
|
53
|
+
it "should respond with a 404" do
|
54
|
+
get "/a_path"
|
48
55
|
|
49
|
-
|
56
|
+
response.status.should eql(404)
|
57
|
+
end
|
50
58
|
|
51
59
|
end
|
52
60
|
|
53
61
|
end
|
54
62
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
+
def issue_stub_request
|
64
|
+
post "/stub", {
|
65
|
+
"uri" => "/a_path",
|
66
|
+
"method" => "a method",
|
67
|
+
"response" => {
|
68
|
+
"status" => 200,
|
69
|
+
"body" => "Foo"
|
70
|
+
}
|
71
|
+
}.to_json
|
63
72
|
end
|
64
73
|
|
65
74
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
describe Http::Stub::Stub do
|
2
|
+
|
3
|
+
let(:stub_uri) { "/a_path" }
|
4
|
+
let(:stub_method) { "get" }
|
5
|
+
let(:stub_parameters) { {} }
|
6
|
+
let(:stub_body) do
|
7
|
+
{
|
8
|
+
"uri" => stub_uri,
|
9
|
+
"method" => stub_method,
|
10
|
+
"parameters" => stub_parameters,
|
11
|
+
"response" => {
|
12
|
+
"status" => 201,
|
13
|
+
"body" => "Foo"
|
14
|
+
}
|
15
|
+
}.to_json
|
16
|
+
end
|
17
|
+
let(:stub_request) { double("HttpRequest", :body => double("HttpRequestBody", :read => stub_body)) }
|
18
|
+
let(:stub_instance) { Http::Stub::Stub.new(stub_request) }
|
19
|
+
|
20
|
+
describe "#stubs?" do
|
21
|
+
|
22
|
+
let(:request_uri) { stub_uri }
|
23
|
+
let(:request_method) { stub_method }
|
24
|
+
let(:request_parameters) { stub_parameters }
|
25
|
+
let(:request) do
|
26
|
+
double("HttpRequest", :path_info => request_uri, :request_method => request_method, :params => request_parameters)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when the request uri matches" do
|
30
|
+
|
31
|
+
describe "and the request method matches" do
|
32
|
+
|
33
|
+
describe "and a parameter match is configured" do
|
34
|
+
|
35
|
+
let(:stub_parameters) do
|
36
|
+
{
|
37
|
+
"param1" => "value1",
|
38
|
+
"param2" => "value2",
|
39
|
+
"param3" => "value3"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "and the parameters match" do
|
44
|
+
|
45
|
+
it "should return true" do
|
46
|
+
stub_instance.stubs?(request).should be_true
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "and the parameter values do not match" do
|
52
|
+
|
53
|
+
let(:request_parameters) do
|
54
|
+
{
|
55
|
+
"param1" => "value1",
|
56
|
+
"param2" => "aDifferentValue",
|
57
|
+
"param3" => "value3"
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should return false" do
|
62
|
+
stub_instance.stubs?(request).should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "and not all parameters are provided" do
|
68
|
+
|
69
|
+
let(:request_parameters) do
|
70
|
+
{
|
71
|
+
"param1" => "value1",
|
72
|
+
"param3" => "value3"
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should be false" do
|
77
|
+
stub_instance.stubs?(request).should be_false
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "when the request uri does not match" do
|
89
|
+
|
90
|
+
let(:request_uri) { "/a_different_path" }
|
91
|
+
|
92
|
+
it "should return false" do
|
93
|
+
stub_instance.stubs?(request).should be_false
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when the request method does not match" do
|
99
|
+
|
100
|
+
let(:request_method) { "post" }
|
101
|
+
|
102
|
+
it "should return false" do
|
103
|
+
stub_instance.stubs?(request).should be_false
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "#response" do
|
111
|
+
|
112
|
+
it "should expose the provided response status" do
|
113
|
+
stub_instance.response.status.should eql(201)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should expose the provided response body" do
|
117
|
+
stub_instance.response.body.should eql("Foo")
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "#to_s" do
|
123
|
+
|
124
|
+
let(:stub_parameters) do
|
125
|
+
{
|
126
|
+
"param1" => "value1",
|
127
|
+
"param2" => "value2",
|
128
|
+
"param3" => "value3"
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return a string containing the stubbed uri" do
|
133
|
+
stub_instance.to_s.should match(/\/a_path/)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should return a string containing the stubbed request method" do
|
137
|
+
stub_instance.to_s.should match(/get/)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should return a string containing the stubbed parameters" do
|
141
|
+
stub_parameters.each_pair do |key, value|
|
142
|
+
stub_instance.to_s.should match(/#{Regexp.escape(key)}/)
|
143
|
+
stub_instance.to_s.should match(/#{Regexp.escape(value)}/)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return a string containing the intended response code" do
|
148
|
+
stub_instance.to_s.should match(/201/)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should return a string containing the intended response body" do
|
152
|
+
stub_instance.to_s.should match(/Foo/)
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: http_stub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-02-
|
13
|
+
date: 2013-02-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: sinatra
|
@@ -28,6 +28,22 @@ dependencies:
|
|
28
28
|
- - ~>
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: 1.3.4
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: immutable_struct
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.1.0
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.1.0
|
31
47
|
description: Configure server responses via requests to /stub. Intended as an acceptance
|
32
48
|
/ integration testing tool.
|
33
49
|
email: matthew.ueckerman@myob.com
|
@@ -37,13 +53,17 @@ extra_rdoc_files: []
|
|
37
53
|
files:
|
38
54
|
- ./lib/http/stub/client.rb
|
39
55
|
- ./lib/http/stub/rake_task.rb
|
56
|
+
- ./lib/http/stub/registry.rb
|
40
57
|
- ./lib/http/stub/server.rb
|
58
|
+
- ./lib/http/stub/stub.rb
|
41
59
|
- ./lib/http/stub/version.rb
|
42
60
|
- ./lib/http_stub.rb
|
43
61
|
- ./spec/curl_sample.txt
|
44
62
|
- ./spec/lib/http/client_integration_spec.rb
|
45
63
|
- ./spec/lib/http/rake_task_integration_spec.rb
|
64
|
+
- ./spec/lib/http/registry_spec.rb
|
46
65
|
- ./spec/lib/http/server_spec.rb
|
66
|
+
- ./spec/lib/http/stub_spec.rb
|
47
67
|
- ./spec/spec_helper.rb
|
48
68
|
- ./spec/support/server_integration.rb
|
49
69
|
homepage: http://github.com/MYOB-Technology/http_stub
|
@@ -67,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
87
|
version: '0'
|
68
88
|
segments:
|
69
89
|
- 0
|
70
|
-
hash:
|
90
|
+
hash: 2752646787075504105
|
71
91
|
requirements: []
|
72
92
|
rubyforge_project: http_stub
|
73
93
|
rubygems_version: 1.8.25
|
@@ -78,6 +98,8 @@ test_files:
|
|
78
98
|
- ./spec/curl_sample.txt
|
79
99
|
- ./spec/lib/http/client_integration_spec.rb
|
80
100
|
- ./spec/lib/http/rake_task_integration_spec.rb
|
101
|
+
- ./spec/lib/http/registry_spec.rb
|
81
102
|
- ./spec/lib/http/server_spec.rb
|
103
|
+
- ./spec/lib/http/stub_spec.rb
|
82
104
|
- ./spec/spec_helper.rb
|
83
105
|
- ./spec/support/server_integration.rb
|