How to patch a method decorated with `flask - route` in testing?

Rumpelstinsk

I have a python application which uses Flask to expose some endpoints. Also, I'm using a fixture, to catch unhandled exceptions and to return a custom response. This is a sample code:

from flask import make_response, Blueprint

root = Blueprint("main", __name__)

@root.errorhandler(Exception)
def custom_error_handler(error):
    #do other things here
    return make_response({"status": "failure", "error": str(error)}), 500

@root.route("/my_url", methods=["POST"])
def my_url_method():
    #do other thins
    return make_response(...), 200

I want to have a test to ensure this works. So, in order to simulate that an unhandled exception has occurred, I'm trying to mock my_url method with a function that simply raise an exception:

from unittest.mock import patch
from flask import Flask

@pytest.fixture
def client(monkeypatch):
    app = Flask(__name__, instance_relative_config=True)
    app.register_blueprint(root)
    app.config["TESTING"] = True

    return app.test_client()

def test_exception(client):
    with patch("[file_link].my_url_method", side_effect=Exception("an error")):
        response = client.post("my_url")
        assert response.status_code == 500

However assertion fails. The method is executed correctly as is not raised any exception, returning 200 as status code.

I think the problem is that mock is not applied when you call the method throw flask. But I don't know how to fix it.

Rumpelstinsk

I found a solution. It's not the most elegant one, but it works. Patching the test with a decorator, works because the patch it's apply before the flask context is created:

@patch("[file_link].my_url_method", side_effect=Exception("an error")
def test_exception(client):
    #some code here

Noticing that, gives me the clue, that the problem relies on flask initialization and pytest fixture creation.

However, doing that way interferes with the creation of flask context, and the decorators applied on each mocked method are not applied correctly.

So, instead of doing a "traditional mock", I'm simply updating the flask reference for the function it have to call on the request:

def mocked_function(**args):
    raise Exception(MOCKED_EXCEPTION_MESSAGE)

def test_exception(client):
     client.application.view_functions["main.my_url_method"] = mocked_function

The client fixture it's created for each test, so it does not interfere either on the rest of the tests in the suite.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How handle PATCH method in Flask route as API?

From Dev

how do decorated functions work in flask/python? (app.route)

From Dev

Testing the Patch odata webapi method

From Dev

Python unit-testing - How to patch an async call internal to the method I am testing

From Dev

How do I override a decorated method in Python?

From Dev

Flask: How to run a method before every route in a blueprint?

From Dev

How to redirect from a PATCH route to a POST route?

From Dev

What do @mock.patch decorators do in Python when there are more than the number of parameters of the decorated method/function?

From Dev

How to call an overriden superclass method from within a decorated subclass method

From Dev

How to patch/mock a method in Swift?

From Java

How to use PATCH method in CXF

From Dev

How to patch an asynchronous class method?

From Dev

How to declare decorator inside a class, to decorate an already decorated, inherited method?

From Dev

How does the unittest library determine whether to run a decorated method?

From Dev

undefined method on decorated instance

From Dev

How to patch a function that a Flask view calls

From Dev

How to properly write a "Patch" endpoint in flask and Pymongo

From Dev

Flask route to method with add_url_rule

From Dev

The GET method is not supported for this route. Supported methods: POST / PATCH / DELETE

From Dev

The GET method is not supported for this route. Supported methods: PATCH, DELETE

From Dev

The POST method is not supported for this route. Supported methods: PUT, PATCH, DELETE

From Dev

The PATCH method is not supported for this route. Supported methods: GET, HEAD

From Dev

Laravel API Route Put/Patch Method : Error - The GET method is not supported for this route

From Dev

How to separate the method to the route

From Dev

How to call method in route?

From Dev

Error: 'The GET method is not supported for this route. Supported methods: PATCH, DELETE.' accessing a route

From Dev

Detect if method is decorated before invoking it

From Dev

getattr on a decorated method generates a TypeError

From Dev

How to patch a module method that is called within a class?

Related Related

  1. 1

    How handle PATCH method in Flask route as API?

  2. 2

    how do decorated functions work in flask/python? (app.route)

  3. 3

    Testing the Patch odata webapi method

  4. 4

    Python unit-testing - How to patch an async call internal to the method I am testing

  5. 5

    How do I override a decorated method in Python?

  6. 6

    Flask: How to run a method before every route in a blueprint?

  7. 7

    How to redirect from a PATCH route to a POST route?

  8. 8

    What do @mock.patch decorators do in Python when there are more than the number of parameters of the decorated method/function?

  9. 9

    How to call an overriden superclass method from within a decorated subclass method

  10. 10

    How to patch/mock a method in Swift?

  11. 11

    How to use PATCH method in CXF

  12. 12

    How to patch an asynchronous class method?

  13. 13

    How to declare decorator inside a class, to decorate an already decorated, inherited method?

  14. 14

    How does the unittest library determine whether to run a decorated method?

  15. 15

    undefined method on decorated instance

  16. 16

    How to patch a function that a Flask view calls

  17. 17

    How to properly write a "Patch" endpoint in flask and Pymongo

  18. 18

    Flask route to method with add_url_rule

  19. 19

    The GET method is not supported for this route. Supported methods: POST / PATCH / DELETE

  20. 20

    The GET method is not supported for this route. Supported methods: PATCH, DELETE

  21. 21

    The POST method is not supported for this route. Supported methods: PUT, PATCH, DELETE

  22. 22

    The PATCH method is not supported for this route. Supported methods: GET, HEAD

  23. 23

    Laravel API Route Put/Patch Method : Error - The GET method is not supported for this route

  24. 24

    How to separate the method to the route

  25. 25

    How to call method in route?

  26. 26

    Error: 'The GET method is not supported for this route. Supported methods: PATCH, DELETE.' accessing a route

  27. 27

    Detect if method is decorated before invoking it

  28. 28

    getattr on a decorated method generates a TypeError

  29. 29

    How to patch a module method that is called within a class?

HotTag

Archive