I created a custom exception handler and wanted to write test cases for it.
This is my Testcase:
def test_is_exception_raised(app_client):
exception = CustomException(InvalidSQLStatement())
with pytest.raises(exception):
raise exception
try:
raise exception
except Exception as e:
assert e.message
assert e.status_code
This is the error I get:
My Code looks like this:
main.py
#app.exception_handler(CustomException)
async def custom_exception_handler(request: Request, exc: CustomException):
log.error(f"{exc}")
return JSONResponse(
status_code=exc.status_code_number,
content=jsonable_encoder({exc.status_code_number: exc.message}),
)
exceptions.py
class CustomException(Exception):
"""
All Custom Exceptions are defined in xyz\exceptions.py
"""
def __init__(self, exception):
if not check_if_exception_exists(exception):
raise KeyError(f"Custom Exception: {exception.__class__.__name__} does not exist.")
self.message = exception.message
self.status_code_number = exception.status_code_number
You need to use raises in the class, like this:
with pytest.raises(CustomException):
Also, you declare status_code_number (in exceptions.py), but use status_code in test case.
Related
I have the following defined in an exceptions.py file:
class Error(Exception):
"""Base exception raised by api wrapper"""
def __init__(self, message: str):
self.message = message
super().__init__(self.message)
# HTTP response exceptions
class ApiBadRequestError(Error):
"""Bad Request –- Incorrect parameters."""
def __init__(self, message: str):
self.message = message
super().__init__(self.message)
I then have a function that correctly raises an ApiBadRequestError exception.
In pytest I'm doing the following:
def test_handle_request_response_raises_correct_exception_for_response_code(
self, status_code, exception_type, client, create_response
):
response = create_response(status_code=status_code)
with pytest.raises(ApiBadRequestError) as e:
a = client._check_response_codes(response)
which is failing the test because inside pytest.raises it's doing isintance(e, ApiBadRequestError) which is returning False. If I however change the test to the following:
def test_handle_request_response_raises_correct_exception_for_response_code(
self, status_code, exception_type, client, create_response
):
response = create_response(status_code=status_code)
with pytest.raises(Exception) as e:
a = client._check_response_codes(response)
it passes as the raised exception is seen as an instance of Exception even though it's an ApiBadRequestError
Any help would be really appreciated as I'm completely stumped here.
How can I catch a 4XX series raise in inner function of an API in Django rest framework?
from rest_framework.exceptions import ValidationError
class DummyView(APIView):
def get(self, request, id):
if id==something:
dummy_function_1(id)
else:
dummy_function_2(id)
return Response()
def dummy_function_1():
try:
validate_1(id)
except ValidationError:
raise ValidationError()
#do something with id
return id
When I send a HTTP GET request, I receive a 5XX series error if exception occurs. I want to get 400 Bad Request error in response.
After lots of effort and I don't know why,
If I specify the exception type of inner function, I will get 5XX series error.
so in dummy function I just wrote :
def dummy_function_1():
try:
validate_1(id)
except Exception: # just exception, Not ValidationError or other exception
raise ValidationError()
I could get 4XX series error
Try this:
def dummy_function_1():
try:
validate_1(id)
except Exception: # just exception, Not ValidationError or other exceptions
raise ValidationError()
I have a python flask app, pseudocode shown below.
#app.route('/predict', methods=['POST'])
def transformation():
try:
var1 = function_1()
# do something with var1
var2 = function_2()
except Exception as e:
return jsonify({'message': '{}: {}'.format(type(e).__name__, e)}), 500
As you see, the POST call handler returns a generic exception message back to the client. But I want to customize those exception messages based on whether they are coming from function_1 or function_2
I looked into this thread and understand that it is possible to do below -
try:
#something1
#something2
except ExceptionType1:
#return xyz
except ExceptionType2:
#return abc
But how would it know that ExceptionType1 is coming from function_1() or function_2(). How should I pass exception from function_1() or function_2() to be caught in the main try-except block?
I am trying to create the following exception and call it in another function:
### The exception
class GoogleAuthError(Exception):
def __init__(self, message, code=403):
self.code = code
self.message = message
### Generating the exception
raise GoogleAuthError(message="There was an error authenticating")
### printing the exception
try:
do_something()
except GoogleAuthError as e:
print(e.message)
Basically, I want it to print "There was an error authenticating". How would I do this properly, or is the above the correct way to do it?
Remove the code argument from your __init__. You aren't using it.
You can also delegate the handling of the error message to the parent Exception class, which already knows about messages
class GoogleAuthError(Exception):
def __init__(self, message):
super().__init__(message)
self.code = 403
try:
raise GoogleAuthError('There was an error authenticating')
except GoogleAuthError as e:
print(e)
# There was an error authenticating
Given this simple Bottle code:
def bar(i):
if i%2 == 0:
return i
raise MyError
#route('/foo')
def foo():
try:
return bar()
except MyError as e:
response.status_code = e.pop('status_code')
return e
How would one write Bottle middleware so the same exception handling is done implicitly, so that code like this can work identically to above:
#route('/foo')
def foo():
return bar()
You can do this elegantly with a plugin leveraging abort:
from bottle import abort
def error_translation(func):
def wrapper(*args,**kwargs):
try:
func(*args,**kwargs)
except ValueError as e:
abort(400, e.message)
return wrapper
app.install(error_translation)
Bottle respect the wsgi spec. You can use a classic wsgi middleware
from bottle import route, default_app, run, request
# push an application in the AppStack
default_app.push()
#route('/foo')
def foo():
raise KeyError()
# error view
#route('/error')
def error():
return 'Sorry an error occured %(myapp.error)r' % request.environ
# get the bottle application. can be a Bottle() instance too
app = default_app.pop()
app.catchall = False
def error_catcher(environ, start_response):
# maybe better to fake the start_response callable but this work
try:
return app.wsgi(environ, start_response)
except Exception as e:
# redirect to the error view if an exception is raised
environ['PATH_INFO'] = '/error'
environ['myapp.error'] = e
return app.wsgi(environ, start_response)
# serve the middleware instead of the applicatio
run(app=error_catcher)
You can use this instead:
from bottle import error, run, route
#error(500)
def error_handler_500(error):
return json.dumps({"status": "error", "message": str(error.exception)})
#route("/")
def index():
a = {}
a['aaa']
run()