protobuf 2.0.0.rc3 → 2.0.0.rc4

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.
Files changed (43) hide show
  1. data/lib/protobuf/cli.rb +1 -2
  2. data/lib/protobuf/{common/exceptions.rb → exceptions.rb} +0 -0
  3. data/lib/protobuf/field/base_field.rb +1 -1
  4. data/lib/protobuf/{common/logger.rb → logger.rb} +21 -0
  5. data/lib/protobuf/message/decoder.rb +2 -2
  6. data/lib/protobuf/message/encoder.rb +6 -4
  7. data/lib/protobuf/rpc/buffer.rb +2 -2
  8. data/lib/protobuf/rpc/client.rb +18 -18
  9. data/lib/protobuf/rpc/connectors/base.rb +3 -8
  10. data/lib/protobuf/rpc/connectors/common.rb +29 -28
  11. data/lib/protobuf/rpc/connectors/em_client.rb +9 -9
  12. data/lib/protobuf/rpc/connectors/eventmachine.rb +11 -9
  13. data/lib/protobuf/rpc/connectors/socket.rb +13 -17
  14. data/lib/protobuf/rpc/connectors/zmq.rb +13 -17
  15. data/lib/protobuf/rpc/error.rb +3 -3
  16. data/lib/protobuf/rpc/server.rb +41 -93
  17. data/lib/protobuf/rpc/servers/evented/server.rb +7 -9
  18. data/lib/protobuf/rpc/servers/evented_runner.rb +0 -11
  19. data/lib/protobuf/rpc/servers/socket/server.rb +8 -7
  20. data/lib/protobuf/rpc/servers/socket/worker.rb +22 -15
  21. data/lib/protobuf/rpc/servers/zmq/server.rb +3 -3
  22. data/lib/protobuf/rpc/servers/zmq/util.rb +1 -1
  23. data/lib/protobuf/rpc/servers/zmq/worker.rb +6 -15
  24. data/lib/protobuf/rpc/service.rb +145 -228
  25. data/lib/protobuf/rpc/service_dispatcher.rb +114 -0
  26. data/lib/protobuf/rpc/stat.rb +46 -33
  27. data/lib/protobuf/version.rb +1 -1
  28. data/lib/protobuf/{common/wire_type.rb → wire_type.rb} +0 -0
  29. data/spec/benchmark/tasks.rb +18 -18
  30. data/spec/functional/evented_server_spec.rb +3 -4
  31. data/spec/functional/socket_server_spec.rb +3 -3
  32. data/spec/functional/zmq_server_spec.rb +3 -3
  33. data/spec/lib/protobuf/{common/logger_spec.rb → logger_spec.rb} +46 -36
  34. data/spec/lib/protobuf/rpc/client_spec.rb +10 -58
  35. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +1 -39
  36. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +3 -6
  37. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +0 -12
  38. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +1 -6
  39. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +94 -0
  40. data/spec/lib/protobuf/rpc/service_spec.rb +132 -45
  41. data/spec/spec_helper.rb +4 -3
  42. data/spec/support/server.rb +8 -4
  43. metadata +41 -35
@@ -5,14 +5,13 @@ describe Protobuf::Rpc::Client do
5
5
  before(:each) do
6
6
  load 'protobuf/evented.rb'
7
7
  ::Protobuf::Rpc::Connector.connector_for_client(true)
8
- ::Test::ResourceService.configure(::Test::ResourceService::DEFAULT_LOCATION)
9
8
  end
10
9
 
11
10
  context "when using fiber based calls" do
12
- it "waits for response when running synchronously" do
11
+ it "waits for response" do
13
12
  EventMachine.fiber_run do
14
13
  StubServer.new(:delay => 3) do |server|
15
- client = Test::ResourceService.client(:async => false)
14
+ client = Test::ResourceService.client
16
15
  start = now
17
16
 
18
17
  client.find(:name => "Test Name", :active => true) do |c|
@@ -33,24 +32,11 @@ describe Protobuf::Rpc::Client do
33
32
  end
34
33
  end
35
34
 
36
- it "doesn't wait for response when running async call inside fiber" do
37
- EventMachine.fiber_run do
38
- StubServer.new(:delay => 3) do |server|
39
- client = Test::ResourceService.client(:async => true)
40
- start = now
41
- client.find(:name => "Test Name", :active => true)
42
-
43
- (now - start).should_not be_within(server.options.delay* 0.10).of(server.options.delay)
44
- end
45
- EM.stop
46
- end
47
- end
48
-
49
- it "throws and error when synchronous code is attempted without 'EventMachine.fiber_run'" do
35
+ it "throws and error when call is attempted without 'EventMachine.fiber_run'" do
50
36
  subject = Proc.new do
51
37
  EventMachine.run do
52
38
  StubServer.new(:delay => 1) do |server|
53
- client = Test::ResourceService.client(:async => false)
39
+ client = Test::ResourceService.client
54
40
  client.find(:name => "Test Name", :active => true)
55
41
  end
56
42
  end
@@ -64,7 +50,7 @@ describe Protobuf::Rpc::Client do
64
50
  test_proc = Proc.new do
65
51
  EventMachine.fiber_run do
66
52
  StubServer.new(:delay => 2) do |server|
67
- client = Test::ResourceService.client(:async => false, :timeout => 1)
53
+ client = Test::ResourceService.client(:timeout => 1)
68
54
  client.find(:name => "Test Name", :active => true) do |cl|
69
55
  cl.on_success {}
70
56
  cl.on_failure {|f| error = f}
@@ -83,7 +69,7 @@ describe Protobuf::Rpc::Client do
83
69
  it "throws a timeout when client timeout is exceeded" do
84
70
  subject = Proc.new do
85
71
  StubServer.new(:delay => 2) do |server|
86
- client = Test::ResourceService.client(:async => false, :timeout => 1)
72
+ client = Test::ResourceService.client(:timeout => 1)
87
73
  client.find(:name => "Test Name", :active => true)
88
74
  end
89
75
  end
@@ -96,7 +82,7 @@ describe Protobuf::Rpc::Client do
96
82
 
97
83
  subject = Proc.new do
98
84
  StubServer.new(:delay => 2) do |server|
99
- client = Test::ResourceService.client(:async => false, :timeout => 1)
85
+ client = Test::ResourceService.client(:timeout => 1)
100
86
  client.find(:name => "Test Name", :active => true) do |c|
101
87
  c.on_failure do |f|
102
88
  failure_message = f.message
@@ -114,6 +100,7 @@ describe Protobuf::Rpc::Client do
114
100
  end
115
101
 
116
102
  context 'when creating a client from a service' do
103
+ before { reset_service_location(Test::ResourceService) }
117
104
 
118
105
  it 'should be able to get a client through the Service#client helper method' do
119
106
  Test::ResourceService.client(:port => 9191).should eq(Protobuf::Rpc::Client.new(:service => Test::ResourceService, :port => 9191))
@@ -130,26 +117,15 @@ describe Protobuf::Rpc::Client do
130
117
  updated_client.options[:port].should eq(54321)
131
118
  end
132
119
 
133
- it 'should be able to define the syncronicity of the client request' do
134
- client = Test::ResourceService.client(:async => false)
135
- client.options[:async].should be_false
136
- client.async?.should be_false
137
-
138
- client = Test::ResourceService.client(:async => true)
139
- client.options[:async].should be_true
140
- client.async?.should be_true
141
- end
142
-
143
120
  it 'should be able to define which service to create itself for' do
144
121
  client = Protobuf::Rpc::Client.new :service => Test::ResourceService
145
122
  client.options[:service].should eq(Test::ResourceService)
146
123
  end
147
124
 
148
125
  it 'should have a hard default for host and port on a service that has not been configured' do
149
- reset_service_location Test::ResourceService
150
126
  client = Test::ResourceService.client
151
- client.options[:host].should eq(Protobuf::Rpc::Service::DEFAULT_LOCATION[:host])
152
- client.options[:port].should eq(Protobuf::Rpc::Service::DEFAULT_LOCATION[:port])
127
+ client.options[:host].should eq(Protobuf::Rpc::Service::DEFAULT_HOST)
128
+ client.options[:port].should eq(Protobuf::Rpc::Service::DEFAULT_PORT)
153
129
  end
154
130
 
155
131
  end
@@ -165,30 +141,6 @@ describe Protobuf::Rpc::Client do
165
141
  client.should_receive(:send_request).and_return(nil)
166
142
  expect { client.find(nil) }.to_not raise_error
167
143
  end
168
-
169
- it 'raises a NameError when accessing a var that does not exist' do
170
- pending
171
- end
172
-
173
- it 'should be able to set and get local variables within client response blocks' do
174
- outer_value = 'OUTER'
175
- inner_value = 'INNER'
176
- client = Test::ResourceService.client(:async => true)
177
-
178
- EM.should_receive(:reactor_running?).and_return(true)
179
- EM.stub!(:next_tick) do
180
- client.success_cb.call(inner_value)
181
- end
182
-
183
- client.find(nil) do |c|
184
- c.on_success do |response|
185
- outer_value.should eq('OUTER')
186
- outer_value = response
187
- end
188
- end
189
- outer_value.should eq(inner_value)
190
- end
191
-
192
144
  end
193
145
 
194
146
  context 'when receiving request objects' do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Protobuf::Rpc::Connectors::Base do
4
4
 
5
5
  let(:opts) do
6
- { async: false, timeout: 60 }
6
+ { :timeout => 60 }
7
7
  end
8
8
 
9
9
  subject { Protobuf::Rpc::Connectors::Base.new(opts) }
@@ -47,42 +47,4 @@ describe Protobuf::Rpc::Connectors::Base do
47
47
  end
48
48
  end
49
49
 
50
- describe '#async?' do
51
- context 'when provided options[:async] is false' do
52
- let(:opts) do
53
- { async: false, timeout: 60 }
54
- end
55
-
56
- subject { Protobuf::Rpc::Connectors::Base.new(opts) }
57
-
58
- it 'returns false' do
59
- subject.async?.should be_false
60
- end
61
- end
62
-
63
- context 'when provided options[:async] is true' do
64
- let(:opts) do
65
- { async: true, timeout: 60 }
66
- end
67
-
68
- subject { Protobuf::Rpc::Connectors::Base.new(opts) }
69
-
70
- it 'returns true' do
71
- subject.async?.should be_true
72
- end
73
- end
74
-
75
- context 'when options doesn\'t denote async' do
76
- let(:opts) do
77
- { timeout: 60 }
78
- end
79
-
80
- subject { Protobuf::Rpc::Connectors::Base.new(opts) }
81
-
82
- it 'returns false' do
83
- subject.async?.should be_false
84
- end
85
- end
86
- end
87
-
88
50
  end
@@ -88,8 +88,7 @@ describe Protobuf::Rpc::Connectors::Common do
88
88
 
89
89
  it "calls #complete before exit" do
90
90
  stats = double("Object")
91
- stats.stub(:end) { true }
92
- stats.stub(:log_stats) { true }
91
+ stats.stub(:stop) { true }
93
92
  subject.stats = stats
94
93
 
95
94
  subject.should_receive(:complete)
@@ -98,8 +97,7 @@ describe Protobuf::Rpc::Connectors::Common do
98
97
 
99
98
  it "calls the #{cb} callback when provided" do
100
99
  stats = double("Object")
101
- stats.stub(:end) { true }
102
- stats.stub(:log_stats) { true }
100
+ stats.stub(:stop) { true }
103
101
  subject.stats = stats
104
102
  _cb = double("Object")
105
103
 
@@ -110,8 +108,7 @@ describe Protobuf::Rpc::Connectors::Common do
110
108
 
111
109
  it "calls the complete callback when provided" do
112
110
  stats = double("Object")
113
- stats.stub(:end) { true }
114
- stats.stub(:log_stats) { true }
111
+ stats.stub(:stop) { true }
115
112
  subject.stats = stats
116
113
  comp_cb = double("Object")
117
114
 
@@ -33,16 +33,4 @@ describe Protobuf::Rpc::Connectors::Socket do
33
33
  subject.instance_variable_get(:@response_data).should eq(data)
34
34
  end
35
35
  end
36
-
37
- context "#check_async" do
38
- it "raises an error when trying to execute asynchronously" do
39
- conn = described_class.new(:async => true)
40
- expect{ conn.__send__(:check_async) }.to raise_error
41
- end
42
-
43
- it "allows execution when synchronous" do
44
- conn = described_class.new(:async => false)
45
- expect{ conn.__send__(:check_async) }.to_not raise_error
46
- end
47
- end
48
36
  end
@@ -18,10 +18,5 @@ describe ::Protobuf::Rpc::Connectors::Zmq do
18
18
  ::ZMQ::Context.stub(:new).and_return(zmq_context_mock)
19
19
  end
20
20
 
21
- it 'raises if async is true' do
22
- expect {
23
- described_class.new(async: true).send_request
24
- }.to raise_error
25
- end
26
-
21
+ pending
27
22
  end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'protobuf/rpc/service_dispatcher'
3
+
4
+ describe Protobuf::Rpc::ServiceDispatcher do
5
+ let(:service_name) { 'Test::ResourceService' }
6
+ let(:method_name) { 'find' }
7
+ let(:request) { Test::ResourceFindRequest.new(:name => 'resource') }
8
+ let(:request_bytes) { request.to_s }
9
+ let(:response) { Test::Resource.new }
10
+ let(:wrapper) do
11
+ Protobuf::Socketrpc::Request.new({ :service_name => service_name,
12
+ :method_name => method_name,
13
+ :request_proto => request_bytes })
14
+
15
+ end
16
+
17
+ subject { described_class.new(wrapper) }
18
+
19
+ context 'creating a new dispatcher' do
20
+ its(:service) { should be_instance_of service_name.constantize }
21
+ its(:callable_method) { should be_a(Method) }
22
+ its(:outer_request) { should eq wrapper }
23
+ its(:error) { should be_nil }
24
+
25
+ context 'when service name is not a valid constant' do
26
+ let(:service_name) { 'FlibbityGibbit' }
27
+ its(:success?) { should be_false }
28
+ its(:error) { should be_instance_of(Protobuf::Rpc::ServiceNotFound) }
29
+ end
30
+
31
+ context 'when method is not defined by the service' do
32
+ let(:method_name) { 'holly_hooby_whaty' }
33
+ its(:success?) { should be_false }
34
+ its(:error) { should be_instance_of(Protobuf::Rpc::MethodNotFound) }
35
+ end
36
+
37
+ context 'when method is defined but is not an rpc method' do
38
+ before do
39
+ class Test::Resource
40
+ def non_rpc_method; end
41
+ end
42
+ end
43
+
44
+ let(:method_name) { 'non_rpc_method' }
45
+ its(:success?) { should be_false }
46
+ its(:error) { should be_instance_of(Protobuf::Rpc::MethodNotFound) }
47
+ end
48
+ end
49
+
50
+ describe '#invoke!' do
51
+ context 'regular invocation' do
52
+ before { subject.callable_method.should_receive(:call) }
53
+ before { subject.service.stub(:response).and_return(response) }
54
+ before { subject.invoke! }
55
+ its(:response) { should be_instance_of Test::Resource }
56
+ its(:success?) { should be_true }
57
+ end
58
+
59
+ context 'when service responds with' do
60
+ context 'a hash object' do
61
+ before { subject.callable_method.should_receive(:call) }
62
+ before { subject.service.stub(:response).and_return({ :name => 'returned' }) }
63
+ before { subject.invoke! }
64
+ its(:success?) { should be_true }
65
+ its(:response) { should eq Test::Resource.new(:name => 'returned') }
66
+ end
67
+
68
+ context 'a type not identified by the rpc definition' do
69
+ before { subject.callable_method.should_receive(:call) }
70
+ before { subject.service.stub(:response).and_return("I'm not a valid response") }
71
+ before { subject.invoke! }
72
+ its(:error) { should be_instance_of(Protobuf::Rpc::BadResponseProto) }
73
+ end
74
+ end
75
+
76
+ context 'when service invokes rpc failed callback' do
77
+ before(:all) do
78
+ class Test::ResourceService
79
+ rpc :find_with_rpc_failed, Test::ResourceFindRequest, Test::Resource
80
+ def find_with_rpc_failed
81
+ rpc_failed('Find failed')
82
+ end
83
+ end
84
+ end
85
+
86
+ let(:method_name) { 'find_with_rpc_failed' }
87
+ before { subject.service.find_with_rpc_failed }
88
+
89
+ its(:success?) { should be_false }
90
+ its(:error) { should be_instance_of(Protobuf::Rpc::RpcFailed) }
91
+ end
92
+ end
93
+
94
+ end
@@ -3,75 +3,162 @@ require 'spec/support/test/resource_service'
3
3
 
4
4
  describe Protobuf::Rpc::Service do
5
5
 
6
- context 'when configuring' do
6
+ context 'class methods' do
7
+ subject { Test::ResourceService }
8
+
7
9
  before :each do
8
10
  reset_service_location Test::ResourceService
9
11
  end
10
12
 
11
- it 'should have a default location configured' do
12
- Test::ResourceService.host.should == Protobuf::Rpc::Service::DEFAULT_LOCATION[:host]
13
- Test::ResourceService.port.should == Protobuf::Rpc::Service::DEFAULT_LOCATION[:port]
13
+ describe '.host' do
14
+ its(:host) { should eq described_class::DEFAULT_HOST }
15
+ end
16
+
17
+ describe '.host=' do
18
+ before { subject.host = 'mynewhost.com' }
19
+ its(:host) { should eq 'mynewhost.com' }
20
+ end
21
+
22
+ describe '.port' do
23
+ its(:port) { should eq described_class::DEFAULT_PORT }
14
24
  end
15
25
 
16
- it "should be able to pre-configure a service location for clients" do
17
- Test::ResourceService.located_at 'google.com:12345'
18
- client = Test::ResourceService.client
19
- client.options[:host].should == 'google.com'
20
- client.options[:port].should == 12345
26
+ describe '.port=' do
27
+ before { subject.port = 12345 }
28
+ its(:port) { should eq 12345 }
21
29
  end
22
30
 
23
- context 'configuring host' do
24
- before(:each) { Test::ResourceService.configure :host => 'somehost.com' }
25
- after(:each) { Test::ResourceService.configure :host => '127.0.0.1' }
31
+ describe '.configure' do
32
+ context 'when providing a host' do
33
+ before { subject.configure(:host => 'mynewhost.com') }
34
+ its(:host) { should eq 'mynewhost.com' }
35
+ end
26
36
 
27
- it 'should be able to configure and read the host' do
28
- Test::ResourceService.host.should == 'somehost.com'
37
+ context 'when providing a port' do
38
+ before { subject.configure(:port => 12345) }
39
+ its(:port) { should eq 12345 }
29
40
  end
30
41
  end
31
42
 
32
- it 'should be able to configure and read the port' do
33
- Test::ResourceService.configure :port => 12345
34
- Test::ResourceService.port.should == 12345
43
+ describe '.located_at' do
44
+ context 'when given location is empty' do
45
+ before { subject.located_at(nil) }
46
+ its(:host) { should eq described_class::DEFAULT_HOST }
47
+ its(:port) { should eq described_class::DEFAULT_PORT }
48
+ end
49
+
50
+ context 'when given location is invalid' do
51
+ before { subject.located_at('i like pie') }
52
+ its(:host) { should eq described_class::DEFAULT_HOST }
53
+ its(:port) { should eq described_class::DEFAULT_PORT }
54
+ end
55
+
56
+ context 'when given location contains a host and port' do
57
+ before { subject.located_at('mynewdomain.com:12345') }
58
+ its(:host) { should eq 'mynewdomain.com' }
59
+ its(:port) { should eq 12345 }
60
+ end
35
61
  end
36
62
 
37
- it 'should skip configuring location if the location passed does not match host:port syntax' do
38
- invalid_locations = [nil, 'myhost:', ':9939', 'badhost123']
39
- invalid_locations.each do |location|
40
- Test::ResourceService.located_at location
41
- Test::ResourceService.host.should == Protobuf::Rpc::Service::DEFAULT_LOCATION[:host]
42
- Test::ResourceService.port.should == Protobuf::Rpc::Service::DEFAULT_LOCATION[:port]
63
+ describe '.client' do
64
+ it 'initializes a client object for this service' do
65
+ client = double('client')
66
+ ::Protobuf::Rpc::Client.should_receive(:new)
67
+ .with(hash_including({ :service => subject,
68
+ :host => subject.host,
69
+ :port => subject.port }))
70
+ .and_return(client)
71
+ subject.client.should eq client
43
72
  end
44
73
  end
45
- end
46
74
 
47
- context 'when server calls the service method' do
75
+ describe '.rpc' do
76
+ before { Test::ResourceService.rpc(:update, Test::ResourceFindRequest, Test::Resource) }
77
+ subject { Test::ResourceService.rpcs[:update] }
78
+ its(:method) { should eq :update }
79
+ its(:request_type) { should eq Test::ResourceFindRequest }
80
+ its(:response_type) { should eq Test::Resource }
81
+ end
48
82
 
49
- before(:all) do
50
- class ::NewTestService < Protobuf::Rpc::Service
51
- rpc :bad_method, Test::ResourceFindRequest, Test::Resource
52
- rpc :bad_var, Test::ResourceFindRequest, Test::Resource
53
- def bad_method
54
- hash = {}
55
- hash[:one].explode
83
+ describe '.rpc_method?' do
84
+ before { Test::ResourceService.rpc(:delete, Test::Resource, Test::Resource) }
85
+
86
+ context 'when given name is a pre-defined rpc method' do
87
+ it 'returns true' do
88
+ subject.rpc_method?(:delete).should be_true
56
89
  end
57
- def bad_var
58
- invalidvar
90
+ end
91
+
92
+ context 'when given name is not a pre-defined rpc method' do
93
+ it 'returns false' do
94
+ subject.rpc_method?(:zoobaboo).should be_false
59
95
  end
60
96
  end
61
97
  end
98
+ end
62
99
 
63
- it 'raises an undefined method name error when calling a method on a non-existant object' do
64
- expect {
65
- req = mock('RequestWrapper', :request_proto => Test::ResourceFindRequest.new(:name => 'mmeh').to_s)
66
- ::NewTestService.new.bad_method(req)
67
- }.to raise_error(NoMethodError)
68
- end
100
+ context 'instance methods' do
101
+ context 'when invoking a service call' do
102
+ before(:all) do
103
+ class ::NewTestService < Protobuf::Rpc::Service
104
+ rpc :find_with_implied_response, Test::ResourceFindRequest, Test::Resource
105
+ def find_with_implied_response
106
+ response.name = 'Implicit response'
107
+ end
108
+
109
+ rpc :find_with_respond_with, Test::ResourceFindRequest, Test::Resource
110
+ def find_with_respond_with
111
+ custom = Test::Resource.new(:name => 'Custom response')
112
+ respond_with(custom)
113
+ end
69
114
 
70
- it 'raises a name error when accessing a non-existant object' do
71
- expect {
72
- req = mock('RequestWrapper', :request_proto => Test::ResourceFindRequest.new(:name => 'mmeh').to_s)
73
- ::NewTestService.new.bad_var(req)
74
- }.to raise_error(NameError)
115
+ rpc :find_with_rpc_failed, Test::ResourceFindRequest, Test::Resource
116
+ def find_with_rpc_failed
117
+ rpc_failed('This is a failed endpoint')
118
+ response.name = 'Name will still be set'
119
+ end
120
+ end
121
+ end
122
+
123
+
124
+ let(:request) do
125
+ Test::ResourceFindRequest.new(:name => 'resource')
126
+ end
127
+
128
+ let(:response) do
129
+ Test::Resource.new
130
+ end
131
+
132
+
133
+ context 'when calling the rpc method' do
134
+ context 'when response is implied' do
135
+ subject { NewTestService.new(:find_with_implied_response, request.serialize_to_string) }
136
+
137
+ before { subject.find_with_implied_response }
138
+ its(:response) { should be_a(Test::Resource) }
139
+ specify { subject.response.name.should eq 'Implicit response' }
140
+ end
141
+
142
+ context 'when using respond_with paradigm' do
143
+ subject { NewTestService.new(:find_with_respond_with, request.serialize_to_string) }
144
+
145
+ before { subject.find_with_respond_with }
146
+ its(:response) { should be_a(Test::Resource) }
147
+ specify { subject.response.name.should eq 'Custom response' }
148
+ end
149
+ end
150
+
151
+ context 'when calling rpc_failed in the method' do
152
+ subject { NewTestService.new(:find_with_rpc_failed, request.serialize_to_string) }
153
+
154
+ it 'invokes the rpc_failed callback with the error' do
155
+ error = nil
156
+ subject.on_rpc_failed(lambda { |err| error = err })
157
+ subject.find_with_rpc_failed
158
+ error.should eq 'This is a failed endpoint'
159
+ subject.response.name.should eq 'Name will still be set'
160
+ end
161
+ end
75
162
  end
76
163
 
77
164
  end