def test_provide_copy_source_client(self): source_client = self.session.create_client( 's3', 'eu-central-1', aws_access_key_id='foo', aws_secret_access_key='bar') source_stubber = Stubber(source_client) source_stubber.activate() self.addCleanup(source_stubber.deactivate) self.add_head_object_response(stubber=source_stubber) self.add_successful_copy_responses() call_kwargs = self.create_call_kwargs() call_kwargs['source_client'] = source_client future = self.manager.copy(**call_kwargs) future.result() # Make sure that all of the responses were properly # used for both clients. source_stubber.assert_no_pending_responses() self.stubber.assert_no_pending_responses()
class TestStubber(unittest.TestCase): def setUp(self): self.event_emitter = hooks.HierarchicalEmitter() self.client = mock.Mock() self.client.meta.events = self.event_emitter self.client.meta.method_to_api_mapping.get.return_value = 'foo' self.stubber = Stubber(self.client) self.validate_parameters_mock = mock.Mock() self.validate_parameters_patch = mock.patch( 'ibm_botocore.stub.validate_parameters', self.validate_parameters_mock) self.validate_parameters_patch.start() def tearDown(self): self.validate_parameters_patch.stop() def emit_get_response_event(self, model=None, request_dict=None, signer=None, context=None): if model is None: model = mock.Mock() model.name = 'foo' handler, response = self.event_emitter.emit_until_response( event_name='before-call.myservice.foo', model=model, params=request_dict, request_signer=signer, context=context) return response def test_stubber_registers_events(self): self.event_emitter = mock.Mock() self.client.meta.events = self.event_emitter self.stubber.activate() # This just ensures that we register at the correct event # and nothing more self.event_emitter.register_first.assert_called_with( 'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY) self.event_emitter.register.assert_called_with('before-call.*.*', mock.ANY, unique_id=mock.ANY) def test_stubber_unregisters_events(self): self.event_emitter = mock.Mock() self.client.meta.events = self.event_emitter self.stubber.activate() self.stubber.deactivate() self.event_emitter.unregister.assert_any_call( 'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY) self.event_emitter.unregister.assert_any_call('before-call.*.*', mock.ANY, unique_id=mock.ANY) def test_context_manager(self): self.event_emitter = mock.Mock() self.client.meta.events = self.event_emitter with self.stubber: # Ensure events are registered in context self.event_emitter.register_first.assert_called_with( 'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY) self.event_emitter.register.assert_called_with('before-call.*.*', mock.ANY, unique_id=mock.ANY) # Ensure events are no longer registered once we leave the context self.event_emitter.unregister.assert_any_call( 'before-parameter-build.*.*', mock.ANY, unique_id=mock.ANY) self.event_emitter.unregister.assert_any_call('before-call.*.*', mock.ANY, unique_id=mock.ANY) def test_add_response(self): response = {'foo': 'bar'} self.stubber.add_response('foo', response) with self.assertRaises(AssertionError): self.stubber.assert_no_pending_responses() def test_add_response_fails_when_missing_client_method(self): del self.client.foo with self.assertRaises(ValueError): self.stubber.add_response('foo', {}) def test_validates_service_response(self): self.stubber.add_response('foo', {}) self.assertTrue(self.validate_parameters_mock.called) def test_validate_ignores_response_metadata(self): service_response = {'ResponseMetadata': {'foo': 'bar'}} service_model = ServiceModel({ 'documentation': '', 'operations': { 'foo': { 'name': 'foo', 'input': { 'shape': 'StringShape' }, 'output': { 'shape': 'StringShape' } } }, 'shapes': { 'StringShape': { 'type': 'string' } } }) op_name = service_model.operation_names[0] output_shape = service_model.operation_model(op_name).output_shape self.client.meta.service_model = service_model self.stubber.add_response('TestOperation', service_response) self.validate_parameters_mock.assert_called_with({}, output_shape) # Make sure service response hasn't been mutated self.assertEqual(service_response, {'ResponseMetadata': { 'foo': 'bar' }}) def test_validates_on_empty_output_shape(self): service_model = ServiceModel({ 'documentation': '', 'operations': { 'foo': { 'name': 'foo' } } }) self.client.meta.service_model = service_model with self.assertRaises(ParamValidationError): self.stubber.add_response('TestOperation', {'foo': 'bar'}) def test_get_response(self): service_response = {'bar': 'baz'} self.stubber.add_response('foo', service_response) self.stubber.activate() response = self.emit_get_response_event() self.assertEqual(response[1], service_response) self.assertEqual(response[0].status_code, 200) def test_get_client_error_response(self): error_code = "foo" service_message = "bar" self.stubber.add_client_error('foo', error_code, service_message) self.stubber.activate() response = self.emit_get_response_event() self.assertEqual(response[1]['Error']['Message'], service_message) self.assertEqual(response[1]['Error']['Code'], error_code) def test_get_client_error_with_extra_error_meta(self): error_code = "foo" error_message = "bar" error_meta = { "Endpoint": "https://foo.bar.baz", } self.stubber.add_client_error('foo', error_code, error_message, http_status_code=301, service_error_meta=error_meta) with self.stubber: response = self.emit_get_response_event() error = response[1]['Error'] self.assertIn('Endpoint', error) self.assertEqual(error['Endpoint'], "https://foo.bar.baz") def test_get_client_error_with_extra_response_meta(self): error_code = "foo" error_message = "bar" stub_response_meta = { "RequestId": "79104EXAMPLEB723", } self.stubber.add_client_error('foo', error_code, error_message, http_status_code=301, response_meta=stub_response_meta) with self.stubber: response = self.emit_get_response_event() actual_response_meta = response[1]['ResponseMetadata'] self.assertIn('RequestId', actual_response_meta) self.assertEqual(actual_response_meta['RequestId'], "79104EXAMPLEB723") def test_get_response_errors_with_no_stubs(self): self.stubber.activate() with self.assertRaises(UnStubbedResponseError): self.emit_get_response_event() def test_assert_no_responses_remaining(self): self.stubber.add_response('foo', {}) with self.assertRaises(AssertionError): self.stubber.assert_no_pending_responses()
class TestStubber(unittest.TestCase): def setUp(self): session = ibm_botocore.session.get_session() config = ibm_botocore.config.Config(signature_version=ibm_botocore.UNSIGNED) self.client = session.create_client('s3', config=config) self.stubber = Stubber(self.client) def test_stubber_returns_response(self): service_response = {'ResponseMetadata': {'foo': 'bar'}} self.stubber.add_response('list_objects', service_response) self.stubber.activate() response = self.client.list_objects(Bucket='foo') self.assertEqual(response, service_response) def test_context_manager_returns_response(self): service_response = {'ResponseMetadata': {'foo': 'bar'}} self.stubber.add_response('list_objects', service_response) with self.stubber: response = self.client.list_objects(Bucket='foo') self.assertEqual(response, service_response) def test_activated_stubber_errors_with_no_registered_stubs(self): self.stubber.activate() # Params one per line for readability. with self.assertRaisesRegexp(StubResponseError, "'Bucket': 'asdfasdfasdfasdf',\n"): self.client.list_objects( Bucket='asdfasdfasdfasdf', Delimiter='asdfasdfasdfasdf', Prefix='asdfasdfasdfasdf', EncodingType='url') def test_stubber_errors_when_stubs_are_used_up(self): self.stubber.add_response('list_objects', {}) self.stubber.activate() self.client.list_objects(Bucket='foo') with self.assertRaises(StubResponseError): self.client.list_objects(Bucket='foo') def test_client_error_response(self): error_code = "AccessDenied" error_message = "Access Denied" self.stubber.add_client_error( 'list_objects', error_code, error_message) self.stubber.activate() with self.assertRaises(ClientError): self.client.list_objects(Bucket='foo') def test_can_add_expected_params_to_client_error(self): self.stubber.add_client_error( 'list_objects', 'Error', 'error', expected_params={'Bucket': 'foo'} ) self.stubber.activate() with self.assertRaises(ClientError): self.client.list_objects(Bucket='foo') def test_can_expected_param_fails_in_client_error(self): self.stubber.add_client_error( 'list_objects', 'Error', 'error', expected_params={'Bucket': 'foo'} ) self.stubber.activate() # We expect an AssertionError instead of a ClientError # because we're calling the operation with the wrong # param value. with self.assertRaises(AssertionError): self.client.list_objects(Bucket='wrong-argument-value') def test_expected_params_success(self): service_response = {} expected_params = {'Bucket': 'foo'} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # This should be called successfully with no errors being thrown # for mismatching expected params. response = self.client.list_objects(Bucket='foo') self.assertEqual(response, service_response) def test_expected_params_fail(self): service_response = {} expected_params = {'Bucket': 'bar'} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # This should call should raise an for mismatching expected params. with self.assertRaisesRegexp(StubResponseError, "{'Bucket': 'bar'},\n"): self.client.list_objects(Bucket='foo') def test_expected_params_mixed_with_errors_responses(self): # Add an error response error_code = "AccessDenied" error_message = "Access Denied" self.stubber.add_client_error( 'list_objects', error_code, error_message) # Add a response with incorrect expected params service_response = {} expected_params = {'Bucket': 'bar'} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # The first call should throw and error as expected. with self.assertRaises(ClientError): self.client.list_objects(Bucket='foo') # The second call should throw an error for unexpected parameters with self.assertRaisesRegexp(StubResponseError, 'Expected parameters'): self.client.list_objects(Bucket='foo') def test_can_continue_to_call_after_expected_params_fail(self): service_response = {} expected_params = {'Bucket': 'bar'} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # Throw an error for unexpected parameters with self.assertRaises(StubResponseError): self.client.list_objects(Bucket='foo') # The stubber should still have the responses queued up # even though the original parameters did not match the expected ones. self.client.list_objects(Bucket='bar') self.stubber.assert_no_pending_responses() def test_still_relies_on_param_validation_with_expected_params(self): service_response = {} expected_params = {'Buck': 'bar'} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # Throw an error for invalid parameters with self.assertRaises(ParamValidationError): self.client.list_objects(Buck='bar') def test_any_ignores_param_for_validation(self): service_response = {} expected_params = {'Bucket': stub.ANY} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.add_response( 'list_objects', service_response, expected_params) try: with self.stubber: self.client.list_objects(Bucket='foo') self.client.list_objects(Bucket='bar') except StubAssertionError: self.fail("stub.ANY failed to ignore parameter for validation.") def test_mixed_any_and_concrete_params(self): service_response = {} expected_params = {'Bucket': stub.ANY, 'Key': 'foo.txt'} self.stubber.add_response( 'head_object', service_response, expected_params) self.stubber.add_response( 'head_object', service_response, expected_params) try: with self.stubber: self.client.head_object(Bucket='foo', Key='foo.txt') self.client.head_object(Bucket='bar', Key='foo.txt') except StubAssertionError: self.fail("stub.ANY failed to ignore parameter for validation.") def test_nested_any_param(self): service_response = {} expected_params = { 'Bucket': 'foo', 'Key': 'bar.txt', 'Metadata': { 'MyMeta': stub.ANY, } } self.stubber.add_response( 'put_object', service_response, expected_params) self.stubber.add_response( 'put_object', service_response, expected_params) try: with self.stubber: self.client.put_object( Bucket='foo', Key='bar.txt', Metadata={ 'MyMeta': 'Foo', } ) self.client.put_object( Bucket='foo', Key='bar.txt', Metadata={ 'MyMeta': 'Bar', } ) except StubAssertionError: self.fail( "stub.ANY failed to ignore nested parameter for validation.") def test_ANY_repr(self): self.assertEqual(repr(stub.ANY), '<ANY>') def test_none_param(self): service_response = {} expected_params = {'Buck': None} self.stubber.add_response( 'list_objects', service_response, expected_params) self.stubber.activate() # Throw an error for invalid parameters with self.assertRaises(StubAssertionError): self.client.list_objects(Buck='bar') def test_many_expected_params(self): service_response = {} expected_params = { 'Bucket': 'mybucket', 'Prefix': 'myprefix', 'Delimiter': '/', 'EncodingType': 'url' } self.stubber.add_response( 'list_objects', service_response, expected_params) try: with self.stubber: self.client.list_objects(**expected_params) except StubAssertionError: self.fail( "Stubber inappropriately raised error for same parameters.")