protobuf 2.0.0.rc3 → 2.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
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