|
20 | 20 |
|
21 | 21 | describe Optimizely::DefaultCmabClient do
|
22 | 22 | let(:mock_http_client) { double('http_client') }
|
23 |
| - let(:mock_logger) { double('logger') } |
| 23 | + let(:spy_logger) { spy('logger') } |
24 | 24 | let(:retry_config) { Optimizely::CmabRetryConfig.new(max_retries: 3, retry_delay: 0.01, max_backoff: 1, backoff_multiplier: 2) }
|
25 |
| - let(:client) { described_class.new(http_client: mock_http_client, logger: mock_logger, retry_config: nil) } |
| 25 | + let(:client) { described_class.new(http_client: mock_http_client, logger: spy_logger, retry_config: nil) } |
26 | 26 | let(:rule_id) { 'test_rule' }
|
27 | 27 | let(:user_id) { 'user123' }
|
28 | 28 | let(:attributes) { {'attr1': 'value1', 'attr2': 'value2'} }
|
|
60 | 60 |
|
61 | 61 | it 'should return HTTP exception without retrying' do
|
62 | 62 | allow(mock_http_client).to receive(:post).and_raise(StandardError.new('Connection error'))
|
63 |
| - allow(mock_logger).to receive(:error) |
| 63 | + |
64 | 64 | expect do
|
65 | 65 | client.fetch_decision(rule_id, user_id, attributes, cmab_uuid)
|
66 | 66 | end.to raise_error(Optimizely::CmabFetchError, /Connection error/)
|
67 | 67 | expect(mock_http_client).to have_received(:post).once
|
68 |
| - expect(mock_logger).to have_received(:error).with(a_string_including('Connection error')) |
| 68 | + expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Connection error')) |
69 | 69 | end
|
70 | 70 |
|
71 | 71 | it 'should not return 200 status without retrying' do
|
|
84 | 84 | timeout: 10
|
85 | 85 | )
|
86 | 86 | )
|
87 |
| - expect(mock_logger).to have_received(:error).with(a_string_including('500')) |
| 87 | + expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('500')) |
88 | 88 | end
|
89 | 89 |
|
90 | 90 | it 'should return invalid json without retrying' do
|
|
104 | 104 | timeout: 10
|
105 | 105 | )
|
106 | 106 | )
|
107 |
| - expect(mock_logger).to have_received(:error).with(a_string_including('Invalid CMAB fetch response')) |
| 107 | + expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Invalid CMAB fetch response')) |
108 | 108 | end
|
109 | 109 |
|
110 | 110 | it 'should return invalid response structure without retrying' do
|
|
123 | 123 | timeout: 10
|
124 | 124 | )
|
125 | 125 | )
|
126 |
| - expect(mock_logger).to have_received(:error).with(a_string_including('Invalid CMAB fetch response')) |
| 126 | + expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Invalid CMAB fetch response')) |
127 | 127 | end
|
128 | 128 |
|
129 | 129 | it 'should return the variation id on first try with retry config but no retry needed' do
|
130 | 130 | client_with_retry = described_class.new(
|
131 | 131 | http_client: mock_http_client,
|
132 |
| - logger: mock_logger, |
| 132 | + logger: spy_logger, |
133 | 133 | retry_config: retry_config
|
134 | 134 | )
|
135 | 135 |
|
|
155 | 155 | it 'should return the variation id on third try with retry config' do
|
156 | 156 | client_with_retry = described_class.new(
|
157 | 157 | http_client: mock_http_client,
|
158 |
| - logger: mock_logger, |
| 158 | + logger: spy_logger, |
159 | 159 | retry_config: retry_config
|
160 | 160 | )
|
161 | 161 |
|
|
167 | 167 | call_sequence = [failure_response, failure_response, success_response]
|
168 | 168 | allow(mock_http_client).to receive(:post) { call_sequence.shift }
|
169 | 169 |
|
170 |
| - allow(mock_logger).to receive(:info) |
171 | 170 | allow_any_instance_of(Object).to receive(:sleep)
|
172 | 171 |
|
173 | 172 | result = client_with_retry.fetch_decision(rule_id, user_id, attributes, cmab_uuid)
|
|
186 | 185 | )
|
187 | 186 |
|
188 | 187 | # Verify retry logging
|
189 |
| - expect(mock_logger).to have_received(:info).with('Retrying CMAB request (attempt 1) after 0.01 seconds...') |
190 |
| - expect(mock_logger).to have_received(:info).with('Retrying CMAB request (attempt 2) after 0.02 seconds...') |
| 188 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...') |
| 189 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...') |
191 | 190 |
|
192 | 191 | # Verify sleep was called with correct backoff times
|
193 | 192 | expect_any_instance_of(Object).to have_received(:sleep).with(0.01)
|
|
197 | 196 | it 'should exhausts all retry attempts' do
|
198 | 197 | client_with_retry = described_class.new(
|
199 | 198 | http_client: mock_http_client,
|
200 |
| - logger: mock_logger, |
| 199 | + logger: spy_logger, |
201 | 200 | retry_config: retry_config
|
202 | 201 | )
|
203 | 202 |
|
|
206 | 205 |
|
207 | 206 | # All attempts fail
|
208 | 207 | allow(mock_http_client).to receive(:post).and_return(failure_response)
|
209 |
| - allow(mock_logger).to receive(:info) |
210 |
| - allow(mock_logger).to receive(:error) |
211 | 208 | allow_any_instance_of(Object).to receive(:sleep)
|
212 | 209 |
|
213 | 210 | expect do
|
|
218 | 215 | expect(mock_http_client).to have_received(:post).exactly(4).times
|
219 | 216 |
|
220 | 217 | # Verify retry logging
|
221 |
| - expect(mock_logger).to have_received(:info).with('Retrying CMAB request (attempt 1) after 0.01 seconds...') |
222 |
| - expect(mock_logger).to have_received(:info).with('Retrying CMAB request (attempt 2) after 0.02 seconds...') |
223 |
| - expect(mock_logger).to have_received(:info).with('Retrying CMAB request (attempt 3) after 0.08 seconds...') |
| 218 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...') |
| 219 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...') |
| 220 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 3) after 0.08 seconds...') |
224 | 221 |
|
225 | 222 | # Verify sleep was called for each retry
|
226 | 223 | expect_any_instance_of(Object).to have_received(:sleep).with(0.01)
|
227 | 224 | expect_any_instance_of(Object).to have_received(:sleep).with(0.02)
|
228 | 225 | expect_any_instance_of(Object).to have_received(:sleep).with(0.08)
|
229 | 226 |
|
230 | 227 | # Verify final error logging
|
231 |
| - expect(mock_logger).to have_received(:error).with(a_string_including('Max retries exceeded for CMAB request')) |
| 228 | + expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Max retries exceeded for CMAB request')) |
232 | 229 | end
|
233 | 230 | end
|
0 commit comments