|
54 | 54 | it 'should return the variation id on success without retrying' do
|
55 | 55 | client = described_class.new(mock_http_client, nil, spy_logger)
|
56 | 56 | mock_response = double('response', status_code: 200, json: {'predictions' => [{'variationId' => 'abc123'}]})
|
57 |
| - allow(mock_http_client).to receive(:post).and_return(mock_response) |
| 57 | + allow(mock_http_client).to receive(:post).and_return(mock_response) |
58 | 58 | result = client.fetch_decision(rule_id, user_id, attributes, cmab_uuid)
|
59 | 59 | expect(result).to eq('abc123')
|
60 | 60 | expect(mock_http_client).to have_received(:post).with(
|
|
65 | 65 | timeout: 10
|
66 | 66 | )
|
67 | 67 | ).once
|
| 68 | + expect(Kernel).not_to have_received(:sleep) |
68 | 69 | end
|
69 | 70 |
|
70 | 71 | it 'should return HTTP exception without retrying' do
|
|
76 | 77 | end.to raise_error(Optimizely::CmabFetchError, /Connection error/)
|
77 | 78 | expect(mock_http_client).to have_received(:post).once
|
78 | 79 | expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Connection error'))
|
| 80 | + expect(Kernel).not_to have_received(:sleep) |
79 | 81 | end
|
80 | 82 |
|
81 | 83 | it 'should not return 200 status without retrying' do
|
|
96 | 98 | )
|
97 | 99 | ).once
|
98 | 100 | expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('500'))
|
| 101 | + expect(Kernel).not_to have_received(:sleep) |
99 | 102 | end
|
100 | 103 |
|
101 | 104 | it 'should return invalid json without retrying' do
|
|
117 | 120 | )
|
118 | 121 | ).once
|
119 | 122 | expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Invalid CMAB fetch response'))
|
| 123 | + expect(Kernel).not_to have_received(:sleep) |
120 | 124 | end
|
121 | 125 |
|
122 | 126 | it 'should return invalid response structure without retrying' do
|
|
137 | 141 | )
|
138 | 142 | ).once
|
139 | 143 | expect(spy_logger).to have_received(:log).with(Logger::ERROR, a_string_including('Invalid CMAB fetch response'))
|
| 144 | + expect(Kernel).not_to have_received(:sleep) |
140 | 145 | end
|
141 | 146 |
|
142 | 147 | it 'should return the variation id on first try with retry config but no retry needed' do
|
|
168 | 173 | success_response = double('response', status_code: 200, json: {'predictions' => [{'variationId' => 'xyz456'}]})
|
169 | 174 |
|
170 | 175 | # First two calls fail, third succeeds
|
171 |
| - call_sequence = [failure_response, failure_response, success_response] |
172 |
| - allow(mock_http_client).to receive(:post) { call_sequence.shift } |
| 176 | + allow(mock_http_client).to receive(:post).and_return(failure_response, failure_response, success_response) |
173 | 177 |
|
174 | 178 | result = client_with_retry.fetch_decision(rule_id, user_id, attributes, cmab_uuid)
|
175 | 179 |
|
176 | 180 | expect(result).to eq('xyz456')
|
177 | 181 | expect(mock_http_client).to have_received(:post).exactly(3).times
|
178 | 182 |
|
179 |
| - # Verify all HTTP calls used correct parameters |
180 |
| - # This expectation should not be here if you want to count calls. |
181 |
| - # It would be better to assert that the last call had the correct parameters, |
182 |
| - # or that *any* call had the correct parameters. |
183 |
| - # For this test, verifying the total call count and sleep times is more relevant. |
184 |
| - # If you want to check the arguments for each of the 3 calls, you'd need a different approach. |
185 |
| - # For now, let's remove this specific `with` expectation to avoid conflicts with `exactly(3).times`. |
186 |
| - # expect(mock_http_client).to have_received(:post).with( |
187 |
| - # expected_url, |
188 |
| - # hash_including( |
189 |
| - # json: expected_body, |
190 |
| - # headers: expected_headers, |
191 |
| - # timeout: 10 |
192 |
| - # ) |
193 |
| - # ) |
194 |
| - |
195 | 183 | # Verify retry logging
|
196 |
| - expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...') |
197 |
| - expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...') |
| 184 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...').once |
| 185 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...').once |
198 | 186 |
|
199 | 187 | # Verify sleep was called with correct backoff times
|
200 | 188 | expect(Kernel).to have_received(:sleep).with(0.01).once
|
201 | 189 | expect(Kernel).to have_received(:sleep).with(0.02).once
|
| 190 | + expect(Kernel).not_to have_received(:sleep).with(0.08) |
202 | 191 | end
|
203 | 192 |
|
204 | 193 | it 'should exhausts all retry attempts' do
|
|
214 | 203 | client_with_retry.fetch_decision(rule_id, user_id, attributes, cmab_uuid)
|
215 | 204 | end.to raise_error(Optimizely::CmabFetchError)
|
216 | 205 |
|
217 |
| - # Verify all attempts were made (1 initial + 3 retries) |
| 206 | + # Verify all attempts were made (1 initial + 3 retries = 4 calls) |
218 | 207 | expect(mock_http_client).to have_received(:post).exactly(4).times
|
219 | 208 |
|
220 | 209 | # Verify retry logging
|
221 |
| - expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...') |
222 |
| - expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...') |
223 |
| - expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 3) after 0.08 seconds...') |
| 210 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 1) after 0.01 seconds...').once |
| 211 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 2) after 0.02 seconds...').once |
| 212 | + expect(spy_logger).to have_received(:log).with(Logger::INFO, 'Retrying CMAB request (attempt 3) after 0.08 seconds...').once |
224 | 213 |
|
225 | 214 | # Verify sleep was called for each retry
|
226 | 215 | expect(Kernel).to have_received(:sleep).with(0.01).once
|
|
0 commit comments