Pytest mocking load wrong value from json file

Viewed 19

I have strange bug when i try to mock external API call from my application in my CI.

It's quite difficult to explain so I'll do my best :p

I load json file from jinj2 template with lib jinja2 & json and load result into a variable and send it into "patch.object".

When I use temp variable, it's doesn't work and I feel like pytest

Code with bug :

import json

import pytest

from unittest import TestCase
from unittest.mock import patch

class TestK8sNamespace(TestCase):
    """Test k8s namespace Endpoint."""

    def test_k8s_namespace_create(self):
        """CHECK Create."""
        if "k8s_namespace" in ENDPOINT_LIST:
            method = "POST"
            if method in ENDPOINT_LIST["k8s_namespace"]:
                for endpoint in ENDPOINT_LIST["k8s_namespace"][method]:
                    if "/environment/" not in endpoint["url"]:
                        print(f"Test {endpoint['url']}")
                        if ENV_TEST == "mock":
                            mock_k8s_namespace_create(endpoint=endpoint, method=method)
                        else:
                            k8s_namespace_create(endpoint=endpoint, method=method)

@patch.object(QueryEnvironment, "get")
@patch.object(QueryEnvironment, "put")
def mock_k8s_namespace_create(mock_put, mock_get, endpoint, method):
    """Mock API Call."""
    ####################################################################
    ### USE TEMP VARIABLE TO AVOID DUPLICATION CODE
    response = json.loads(
        TEST_TEMPLATE.get_template("management_zones.json").render(
            management_zone=management_zone_format(mz)
        ),
    )
    response_detail = json.loads(
        TEST_TEMPLATE.get_template("management_zones_detail_init.json").render(
           management_zone=management_zone_format(mz),
           management_zone_id=0,
        )
    )
    side_effect = []
    step_create = [response, response, response_detail, response_detail, response, response_detail]
    ### USE TEMP VARIABLE TO AVOID DUPLICATION CODE
    ####################################################################
    if "/environment/" in endpoint["url"]:
        side_effect = step_create
    else:
        for _ in ENVIRONMENTS:
            side_effect = [*step_create, *step_create]
    mock_get.side_effect = side_effect
    mock_put.return_value = ""
    k8s_namespace_create(endpoint=endpoint, method=method)

def k8s_namespace_create(endpoint, method):
    """Check k8s namespace creation after MZ init."""
     if "/environment/" in endpoint["url"]:
        response = call_api(method=method, url=endpoint["url"])
        assert response.status_code == 200
        result = response.json()
        assert not result["error"]
        assert result["status_code"] == 200
        assert result["error_description"] == ""
        assert result["items"] != {}
    else:
        response = call_api(method=method, url=endpoint["url"])
        assert response.status_code == 200
        result = response.json()
        for _env in ENVIRONMENTS:
            assert not result[_env]["error"]
            assert result[_env]["status_code"] == 200
            assert result[_env]["error_description"] == ""
            assert result[_env]["items"] != {}

When i run this code variable response_detail have content of other file in my folder oO

Code working good :

import json

import pytest

from unittest import TestCase
from unittest.mock import patch

class TestK8sNamespace(TestCase):
    """Test k8s namespace Endpoint."""

    def test_k8s_namespace_create(self):
        """CHECK Create."""
        if "k8s_namespace" in ENDPOINT_LIST:
            method = "POST"
            if method in ENDPOINT_LIST["k8s_namespace"]:
                for endpoint in ENDPOINT_LIST["k8s_namespace"][method]:
                    if "/environment/" not in endpoint["url"]:
                        print(f"Test {endpoint['url']}")
                        if ENV_TEST == "mock":
                            mock_k8s_namespace_create(endpoint=endpoint, method=method)
                        else:
                            k8s_namespace_create(endpoint=endpoint, method=method)

@patch.object(QueryEnvironment, "get")
@patch.object(QueryEnvironment, "put")
def mock_k8s_namespace_create(mock_put, mock_get, endpoint, method):
    """Mock API Call."""
    side_effect = []
    ####################################################################
    ### REMOVE TEMP VARIABLE TO AVOID DUPLICATION CODE
    step_create = [json.loads(
        TEST_TEMPLATE.get_template("management_zones.json").render(
            management_zone=management_zone_format(mz)
        ),
    ), json.loads(
        TEST_TEMPLATE.get_template("management_zones.json").render(
            management_zone=management_zone_format(mz)
        ),
    ), json.loads(
        TEST_TEMPLATE.get_template("management_zones_detail_init.json").render(
           management_zone=management_zone_format(mz),
           management_zone_id=0,
        )
    ), json.loads(
        TEST_TEMPLATE.get_template("management_zones_detail_init.json").render(
           management_zone=management_zone_format(mz),
           management_zone_id=0,
        )
    ), json.loads(
        TEST_TEMPLATE.get_template("management_zones.json").render(
            management_zone=management_zone_format(mz)
        ),
    ), json.loads(
        TEST_TEMPLATE.get_template("management_zones_detail_init.json").render(
           management_zone=management_zone_format(mz),
           management_zone_id=0,
        )
    )]
    ### REMOVE TEMP VARIABLE TO AVOID DUPLICATION CODE
    ####################################################################
    if "/environment/" in endpoint["url"]:
        side_effect = step_create
    else:
        for _ in ENVIRONMENTS:
            side_effect = [*step_create, *step_create]
    mock_get.side_effect = side_effect
    mock_put.return_value = ""
    k8s_namespace_create(endpoint=endpoint, method=method)

def k8s_namespace_create(endpoint, method):
    """Check k8s namespace creation after MZ init."""
     if "/environment/" in endpoint["url"]:
        response = call_api(method=method, url=endpoint["url"])
        assert response.status_code == 200
        result = response.json()
        assert not result["error"]
        assert result["status_code"] == 200
        assert result["error_description"] == ""
        assert result["items"] != {}
    else:
        response = call_api(method=method, url=endpoint["url"])
        assert response.status_code == 200
        result = response.json()
        for _env in ENVIRONMENTS:
            assert not result[_env]["error"]
            assert result[_env]["status_code"] == 200
            assert result[_env]["error_description"] == ""
            assert result[_env]["items"] != {}

When I run this test, "response_detail" have content of my file management_zones_detail_init.json

I have print content of value side_effect just after line mock_get.side_effect = side_effect and content is good in both cases.

I removed all the definitions from the file that is loaded instead of "management_zones_detail_init.json", but after this it's always the wrong file that is loaded oO

Have you idea why ?

0 Answers
Related