http_stub 0.1.4 → 0.2.0
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.rb +7 -3
- data/lib/http_stub/configurer.rb +75 -0
- data/lib/http_stub/controllers/alias_controller.rb +29 -0
- data/lib/http_stub/controllers/stub_controller.rb +27 -0
- data/lib/http_stub/models/alias.rb +22 -0
- data/lib/http_stub/models/registry.rb +29 -0
- data/lib/http_stub/models/stub.rb +35 -0
- data/lib/http_stub/response.rb +14 -0
- data/lib/http_stub/server.rb +24 -9
- data/lib/http_stub/start_server_rake_task.rb +1 -1
- data/lib/http_stub/version.rb +1 -1
- data/spec/lib/http_stub/configurer_integration_spec.rb +119 -0
- data/spec/lib/http_stub/controllers/alias_controller_spec.rb +75 -0
- data/spec/lib/http_stub/controllers/stub_controller_spec.rb +74 -0
- data/spec/lib/http_stub/models/alias_spec.rb +58 -0
- data/spec/lib/http_stub/models/registry_spec.rb +101 -0
- data/spec/lib/http_stub/{stub_spec.rb → models/stub_spec.rb} +18 -19
- data/spec/lib/http_stub/response_spec.rb +73 -0
- data/spec/lib/http_stub/server_spec.rb +117 -44
- data/spec/lib/http_stub/start_server_rake_task_integration_spec.rb +1 -1
- metadata +23 -11
- data/lib/http_stub/client.rb +0 -61
- data/lib/http_stub/registry.rb +0 -26
- data/lib/http_stub/stub.rb +0 -35
- data/spec/lib/http_stub/client_integration_spec.rb +0 -81
- data/spec/lib/http_stub/registry_spec.rb +0 -99
data/lib/http_stub.rb
CHANGED
@@ -7,7 +7,11 @@ require 'immutable_struct'
|
|
7
7
|
require 'net/http'
|
8
8
|
require 'json'
|
9
9
|
|
10
|
-
require File.expand_path('../http_stub/
|
11
|
-
require File.expand_path('../http_stub/
|
10
|
+
require File.expand_path('../http_stub/response', __FILE__)
|
11
|
+
require File.expand_path('../http_stub/models/stub', __FILE__)
|
12
|
+
require File.expand_path('../http_stub/models/alias', __FILE__)
|
13
|
+
require File.expand_path('../http_stub/models/registry', __FILE__)
|
14
|
+
require File.expand_path('../http_stub/controllers/stub_controller', __FILE__)
|
15
|
+
require File.expand_path('../http_stub/controllers/alias_controller', __FILE__)
|
12
16
|
require File.expand_path('../http_stub/server', __FILE__)
|
13
|
-
require File.expand_path('../http_stub/
|
17
|
+
require File.expand_path('../http_stub/configurer', __FILE__)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module HttpStub
|
2
|
+
|
3
|
+
module Configurer
|
4
|
+
|
5
|
+
def self.included(mod)
|
6
|
+
mod.extend(HttpStub::Configurer::ClassMethods)
|
7
|
+
mod.send(:include, HttpStub::Configurer::InstanceMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def host(host)
|
13
|
+
@host = host
|
14
|
+
end
|
15
|
+
|
16
|
+
def port(port)
|
17
|
+
@port = port
|
18
|
+
end
|
19
|
+
|
20
|
+
def stub_alias(alias_uri, stub_uri, options)
|
21
|
+
response_options = options[:response]
|
22
|
+
request = Net::HTTP::Post.new("/stubs/aliases")
|
23
|
+
request.content_type = "application/json"
|
24
|
+
request.body = {
|
25
|
+
"alias_uri" => alias_uri,
|
26
|
+
"uri" => stub_uri,
|
27
|
+
"method" => options[:method],
|
28
|
+
"parameters" => options[:parameters] || {},
|
29
|
+
"response" => {
|
30
|
+
"status" => response_options[:status] || "200",
|
31
|
+
"body" => response_options[:body]
|
32
|
+
}
|
33
|
+
}.to_json
|
34
|
+
response = submit(request)
|
35
|
+
raise "Unable to establish stub alias: #{response.message}" unless response.code == "200"
|
36
|
+
end
|
37
|
+
|
38
|
+
def submit(request)
|
39
|
+
Net::HTTP.new(@host, @port).start { |http| http.request(request) }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
module InstanceMethods
|
45
|
+
|
46
|
+
def stub!(uri, options)
|
47
|
+
response_options = options[:response]
|
48
|
+
request = Net::HTTP::Post.new("/stubs")
|
49
|
+
request.content_type = "application/json"
|
50
|
+
request.body = {
|
51
|
+
"uri" => uri,
|
52
|
+
"method" => options[:method],
|
53
|
+
"parameters" => options[:parameters] || {},
|
54
|
+
"response" => {
|
55
|
+
"status" => response_options[:status] || "200",
|
56
|
+
"body" => response_options[:body]
|
57
|
+
}
|
58
|
+
}.to_json
|
59
|
+
response = self.class.submit(request)
|
60
|
+
raise "Unable to establish stub: #{response.message}" unless response.code == "200"
|
61
|
+
end
|
62
|
+
|
63
|
+
alias_method :stub_response!, :stub!
|
64
|
+
|
65
|
+
def clear!
|
66
|
+
request = Net::HTTP::Delete.new("/stubs")
|
67
|
+
response = self.class.submit(request)
|
68
|
+
raise "Unable to clear stubs: #{response.message}" unless response.code == "200"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpStub
|
2
|
+
module Controllers
|
3
|
+
|
4
|
+
class AliasController
|
5
|
+
|
6
|
+
def initialize(alias_registry, stub_registry)
|
7
|
+
@alias_registry = alias_registry
|
8
|
+
@stub_registry = stub_registry
|
9
|
+
end
|
10
|
+
|
11
|
+
def register(request)
|
12
|
+
@alias_registry.add(HttpStub::Models::Alias.new(request.body.read), request)
|
13
|
+
HttpStub::Response::SUCCESS
|
14
|
+
end
|
15
|
+
|
16
|
+
def activate(request)
|
17
|
+
the_alias = @alias_registry.find_for(request)
|
18
|
+
if the_alias
|
19
|
+
@stub_registry.add(the_alias.the_stub, request)
|
20
|
+
HttpStub::Response::SUCCESS
|
21
|
+
else
|
22
|
+
HttpStub::Response::EMPTY
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module HttpStub
|
2
|
+
module Controllers
|
3
|
+
|
4
|
+
class StubController
|
5
|
+
|
6
|
+
def initialize(registry)
|
7
|
+
@registry = registry
|
8
|
+
end
|
9
|
+
|
10
|
+
def register(request)
|
11
|
+
@registry.add(HttpStub::Models::Stub.new(request.body.read), request)
|
12
|
+
HttpStub::Response::SUCCESS
|
13
|
+
end
|
14
|
+
|
15
|
+
def replay(request)
|
16
|
+
stub = @registry.find_for(request)
|
17
|
+
stub ? stub.response : HttpStub::Response::EMPTY
|
18
|
+
end
|
19
|
+
|
20
|
+
def clear(request)
|
21
|
+
@registry.clear(request)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module HttpStub
|
2
|
+
module Models
|
3
|
+
|
4
|
+
class Alias
|
5
|
+
|
6
|
+
def initialize(request_body)
|
7
|
+
@data = JSON.parse(request_body)
|
8
|
+
@stub = HttpStub::Models::Stub.new(request_body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def satisfies?(request)
|
12
|
+
@data["alias_uri"] == request.path_info
|
13
|
+
end
|
14
|
+
|
15
|
+
def the_stub
|
16
|
+
@stub
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module HttpStub
|
2
|
+
module Models
|
3
|
+
|
4
|
+
class Registry
|
5
|
+
|
6
|
+
def initialize(model_name)
|
7
|
+
@model_name = model_name
|
8
|
+
@models = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(model, request)
|
12
|
+
@models.unshift(model)
|
13
|
+
request.logger.info "Registered #{@model_name}: #{model}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_for(request)
|
17
|
+
request.logger.info "Finding #{@model_name} satisfying: #{request.inspect}"
|
18
|
+
@models.find { |model| model.satisfies?(request) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def clear(request)
|
22
|
+
request.logger.info "Clearing #{@model_name} registry"
|
23
|
+
@models.clear
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module HttpStub
|
2
|
+
module Models
|
3
|
+
|
4
|
+
class Stub
|
5
|
+
|
6
|
+
attr_reader :response
|
7
|
+
|
8
|
+
def initialize(request_body)
|
9
|
+
@data = JSON.parse(request_body)
|
10
|
+
@response = HttpStub::Response.new(status: @data["response"]["status"], body: @data["response"]["body"])
|
11
|
+
end
|
12
|
+
|
13
|
+
def satisfies?(request)
|
14
|
+
@data["uri"] == request.path_info &&
|
15
|
+
@data["method"].downcase == request.request_method.downcase &&
|
16
|
+
parameters_match?(request)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@data.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def parameters_match?(request)
|
26
|
+
parameters = @data["parameters"]
|
27
|
+
parameters.nil? || parameters.reduce(true) do |result, parameter|
|
28
|
+
result && (request.params[parameter[0]] == parameter[1])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module HttpStub
|
2
|
+
|
3
|
+
class Response < ImmutableStruct.new(:status, :body)
|
4
|
+
SUCCESS = HttpStub::Response.new(status: 200, body: "")
|
5
|
+
ERROR = HttpStub::Response.new(status: 404, body: "")
|
6
|
+
EMPTY = HttpStub::Response.new()
|
7
|
+
|
8
|
+
def empty?
|
9
|
+
self == HttpStub::Response::EMPTY
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/lib/http_stub/server.rb
CHANGED
@@ -6,7 +6,10 @@ module HttpStub
|
|
6
6
|
|
7
7
|
def initialize
|
8
8
|
super()
|
9
|
-
@
|
9
|
+
@stub_registry = HttpStub::Models::Registry.new("stub")
|
10
|
+
@alias_registry = HttpStub::Models::Registry.new("alias")
|
11
|
+
@stub_controller = HttpStub::Controllers::StubController.new(@stub_registry)
|
12
|
+
@alias_controller = HttpStub::Controllers::AliasController.new(@alias_registry, @stub_registry)
|
10
13
|
end
|
11
14
|
|
12
15
|
private
|
@@ -32,23 +35,35 @@ module HttpStub
|
|
32
35
|
# "body": "Hello World"
|
33
36
|
# }
|
34
37
|
# }
|
35
|
-
post "/
|
36
|
-
@
|
37
|
-
halt
|
38
|
+
post "/stubs" do
|
39
|
+
response = @stub_controller.register(request)
|
40
|
+
halt(response.status, response.body)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sample request body:
|
44
|
+
# {
|
45
|
+
# "alias_uri": "/some/path",
|
46
|
+
# ... see /stub ...
|
47
|
+
# }
|
48
|
+
post "/stubs/aliases" do
|
49
|
+
response = @alias_controller.register(request)
|
50
|
+
halt(response.status, response.body)
|
38
51
|
end
|
39
52
|
|
40
53
|
delete "/stubs" do
|
41
|
-
@
|
54
|
+
@stub_controller.clear(request)
|
42
55
|
halt 200
|
43
56
|
end
|
44
57
|
|
45
|
-
any_request_type(//) {
|
58
|
+
any_request_type(//) { handle_request }
|
46
59
|
|
47
60
|
private
|
48
61
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
62
|
+
def handle_request
|
63
|
+
response = @stub_controller.replay(request)
|
64
|
+
response = @alias_controller.activate(request) if response.empty?
|
65
|
+
response = HttpStub::Response::ERROR if response.empty?
|
66
|
+
halt(response.status, response.body)
|
52
67
|
end
|
53
68
|
|
54
69
|
end
|
data/lib/http_stub/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
describe HttpStub::Configurer do
|
2
|
+
include_context "server integration"
|
3
|
+
|
4
|
+
before(:all) do
|
5
|
+
class TestConfigurer
|
6
|
+
include HttpStub::Configurer
|
7
|
+
|
8
|
+
host "localhost"
|
9
|
+
port 8001
|
10
|
+
|
11
|
+
stub_alias "/an_alias", "/path1", method: :get, response: { status: 200, body: "Stub alias body" }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:configurer) { TestConfigurer.new }
|
16
|
+
|
17
|
+
after(:each) { configurer.clear! }
|
18
|
+
|
19
|
+
describe "when a stub alias is activated" do
|
20
|
+
|
21
|
+
before(:each) { Net::HTTP.get_response("localhost", "/an_alias", 8001) }
|
22
|
+
|
23
|
+
describe "and the stub request is made" do
|
24
|
+
|
25
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path1", 8001) }
|
26
|
+
|
27
|
+
it "should replay the stubbed response" do
|
28
|
+
response.code.should eql("200")
|
29
|
+
response.body.should eql("Stub alias body")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "when a stub alias is not activated" do
|
37
|
+
|
38
|
+
describe "and the stub request is made" do
|
39
|
+
|
40
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path1", 8001) }
|
41
|
+
|
42
|
+
it "should respond with a 404 status code" do
|
43
|
+
response.code.should eql("404")
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "when a response for a request is stubbed" do
|
51
|
+
|
52
|
+
describe "that contains no parameters" do
|
53
|
+
|
54
|
+
before(:each) do
|
55
|
+
configurer.stub_response!("/path2", method: :get, response: { status: 201, body: "Stub body" })
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "and that request is made" do
|
59
|
+
|
60
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path2", 8001) }
|
61
|
+
|
62
|
+
it "should replay the stubbed response" do
|
63
|
+
response.code.should eql("201")
|
64
|
+
response.body.should eql("Stub body")
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "and the stub is cleared" do
|
70
|
+
|
71
|
+
before(:each) { configurer.clear! }
|
72
|
+
|
73
|
+
describe "and the original request is made" do
|
74
|
+
|
75
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path2", 8001) }
|
76
|
+
|
77
|
+
it "should respond with a 404 status code" do
|
78
|
+
response.code.should eql("404")
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "that contains parameters" do
|
88
|
+
|
89
|
+
before(:each) do
|
90
|
+
configurer.stub_response!("/path3", method: :get, parameters: { key: "value" },
|
91
|
+
response: { status: 202, body: "Another stub body" })
|
92
|
+
end
|
93
|
+
|
94
|
+
describe "and that request is made" do
|
95
|
+
|
96
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path3?key=value", 8001) }
|
97
|
+
|
98
|
+
it "should replay the stubbed response" do
|
99
|
+
response.code.should eql("202")
|
100
|
+
response.body.should eql("Another stub body")
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "and a request with different parameters is made" do
|
106
|
+
|
107
|
+
let(:response) { Net::HTTP.get_response("localhost", "/path3?key=another_value", 8001) }
|
108
|
+
|
109
|
+
it "should respond with a 404 status code" do
|
110
|
+
response.code.should eql("404")
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
describe HttpStub::Controllers::AliasController do
|
2
|
+
|
3
|
+
let(:request_body) { "Some request body" }
|
4
|
+
let(:request) { double("HttpRequest", body: double("RequestBody", read: request_body)) }
|
5
|
+
let(:the_stub) { double(HttpStub::Models::Stub) }
|
6
|
+
let(:stub_alias) { double(HttpStub::Models::Alias, the_stub: the_stub) }
|
7
|
+
let(:alias_registry) { double("HttpStub::Models::AliasRegistry").as_null_object }
|
8
|
+
let(:stub_registry) { double("HttpStub::Models::StubRegistry").as_null_object }
|
9
|
+
let(:controller) { HttpStub::Controllers::AliasController.new(alias_registry, stub_registry) }
|
10
|
+
|
11
|
+
describe "#register" do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
HttpStub::Models::Alias.stub!(:new).and_return(stub_alias)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should create an alias from the request body" do
|
18
|
+
HttpStub::Models::Alias.should_receive(:new).with(request_body).and_return(stub_alias)
|
19
|
+
|
20
|
+
controller.register(request)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should add the created alias to the alias registry" do
|
24
|
+
alias_registry.should_receive(:add).with(stub_alias, request)
|
25
|
+
|
26
|
+
controller.register(request)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a success response" do
|
30
|
+
controller.register(request).should eql(HttpStub::Response::SUCCESS)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#activate" do
|
36
|
+
|
37
|
+
describe "when an alias has been registered that is activated by the request" do
|
38
|
+
|
39
|
+
before(:each) do
|
40
|
+
alias_registry.stub!(:find_for).with(request).and_return(stub_alias)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should add the aliases stub to the stub registry" do
|
44
|
+
stub_registry.should_receive(:add).with(the_stub, request)
|
45
|
+
|
46
|
+
controller.activate(request)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return a success response" do
|
50
|
+
controller.activate(request).should eql(HttpStub::Response::SUCCESS)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when no alias is activated by the request" do
|
56
|
+
|
57
|
+
before(:each) do
|
58
|
+
alias_registry.stub!(:find_for).with(request).and_return(nil)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not add a stub to the registry" do
|
62
|
+
stub_registry.should_not_receive(:add)
|
63
|
+
|
64
|
+
controller.activate(request)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return an empty response" do
|
68
|
+
controller.activate(request).should eql(HttpStub::Response::EMPTY)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|