diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 5ec9ae321..3fe391cd3 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -400,7 +400,10 @@ class ResponseObject(_TemplateEnvironmentMixin): upload_id = query['uploadId'][0] self.backend.cancel_multipart(bucket_name, upload_id) return 204, headers, "" - removed_key = self.backend.delete_key(bucket_name, key_name) + try: + removed_key = self.backend.delete_key(bucket_name, key_name) + except KeyError: + return 404, headers, "" template = self.response_template(S3_DELETE_OBJECT_SUCCESS) return 204, headers, template.render(bucket=removed_key) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 7138d2de3..662b22cbb 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -210,6 +210,7 @@ def test_multipart_invalid_order(): bucket.complete_multipart_upload.when.called_with( multipart.key_name, multipart.id, xml).should.throw(S3ResponseError) + @mock_s3 @reduced_min_part_size def test_multipart_duplicate_upload(): @@ -226,7 +227,8 @@ def test_multipart_duplicate_upload(): multipart.complete_upload() # We should get only one copy of part 1. bucket.get_key("the-key").get_contents_as_string().should.equal(part1 + part2) - + + @mock_s3 def test_list_multiparts(): # Create Bucket so that test can run @@ -475,6 +477,14 @@ def test_post_with_metadata_to_bucket(): bucket.get_key('the-key').get_metadata('test').should.equal('metadata') +@mock_s3 +def test_delete_missing_key(): + conn = boto.connect_s3('the_key', 'the_secret') + bucket = conn.create_bucket('foobar') + + bucket.delete_key.when.called_with('foobar').should.throw(S3ResponseError) + + @mock_s3 def test_delete_keys(): conn = boto.connect_s3('the_key', 'the_secret')