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 ?