[Python] Give side effect to only first call of Pytest patched function

Discussão em 'Python' iniciado por Stack, Outubro 24, 2024.

  1. Stack

    Stack Membro Participativo

    I have a function that renders HTML templates. In case exception is thrown during rendering of a given template, a default template will be rendered (simplified version of the function below):

    def main(path_to_template):
    try:
    return render_template(path_to_template)
    except Exception:
    return render_template('default.html')


    I would like to test the exception block. In my test function I wanted to patch render_template, so that it has an Exception side effect. This must be limited to the first call only however, since I want the second call to return whatever render_template is doing.

    Is it possible to create such a test?

    I tried the following solutions, but none work:

    def test_main():
    mocker.patch("path.to.render_template", side_effect=Exception("mock exception"))
    main("some_path")


    The above is the first approach and it will raise Exception in both calls, hence not test what I want to test.

    def test_main():
    mocker.patch("path.to.render_template", side_effect=[Exception("mock exception"), None])
    main("some_path")


    The above also does not work because the return of render_template is not supposed to be None.

    def custom_side_effect(*args):
    if args[0] == "some_path":
    raise Exception("mock exception")
    else:
    return render_template(args[0])

    def test_main():
    mocker.patch("path.to.render_template", side_effect=custom_side_effect)
    main("some_path")


    The last one results in a circular exception throwing and I have to kill the test run.

    The problem seems to be something standard with an easy solution. Has anyone experienced a similar issue and can suggest the way to solve it?

    EDIT 1: The original test is a functional test using Selenium, where I want to test a scenario of a server error that should result in displaying HTTP 500 Error page. Below the original function under test:

    @login_required(login_url="/login/")
    def pages(request):
    context = {}
    try:
    # remove trailing slash to determine a template
    path = request.path.rstrip("/")
    load_template = path.split("/")[-1]
    if load_template == "admin":
    return HttpResponseRedirect(reverse("admin:index"))
    context["segment"] = load_template
    html_template = loader.get_template("home/" + load_template)
    except template.TemplateDoesNotExist as e:
    html_template = loader.get_template("home/page-404.html")
    except Exception as e:
    html_template = loader.get_template("home/page-500.html")
    return HttpResponse(html_template.render(context, request))


    EDIT 2: As a temporary solution I decided to do small refactoring.

    def load_home_page(path_to_template):
    return loader.get_template(path_to_template)


    def load_404_page():
    return loader.get_template("home/page-404.html")


    def load_500_page():
    return loader.get_template("home/page-500.html")


    Then I only patch load_home_page function.

    I don't think this is the best solution, so it would be great to see something cleaner.

    Continue reading...

Compartilhe esta Página