使用 mock.patch() 时出现 ModuleNotFoundError
ModuleNotFoundError when using mock.patch()
我想模拟来自 Python Kubernetes 客户端的响应。下面是我的 Kubernetes 服务的代码:
import os
from kubernetes.client.rest import ApiException
from kubernetes import client
from kubernetes.config import load_config
from exceptions.logs_not_found_exceptions import LogsNotFound
import logging
log = logging.getLogger("services/kubernetes_service.py")
class KubernetesService:
def __init__(self):
super().__init__()
if os.getenv("DISABLE_KUBERNETES_CONFIG") == "False":
load_config()
self.api_instance = client.CoreV1Api()
def get_namespaces(self):
try:
api_response = self.api_instance.list_namespace()
dict_response = api_response.to_dict()
namespaces = []
for item in dict_response['items']:
namespaces.append(item['metadata']['name'])
log.info(f"Retrieved the namespaces: {namespaces}")
return namespaces
except ApiException as e:
raise e
当我想使用 mock.patch 模拟这个时,我收到了 ModuleNotFoundError。下面是我的测试代码 class
import os
from unittest import mock
from tests.unit_tests import utils
from services.kubernetes_service import KubernetesService
class TestKubernetesService:
@mock.patch.dict(os.environ, {"DISABLE_KUBERNETES_CONFIG": "True"})
def test_get_namespaces(self):
self.service = KubernetesService()
print(self.service.api_instance)
with mock.patch('services.kubernetes_service.KubernetesService.api_instance.list_namespace',
return_value=utils.kubernetes_namespaces_response()):
actual_result = self.service.get_namespaces()
assert actual_result == ['default', 'kube-node-lease', 'kube-public', 'kube-system']
当我将 mock.patch
中的路径从 services.kubernetes_service.KubernetesService.api_instance.list_namespace
编辑到 services.kubernetes_service.KubernetesService.get_namespaces
时,它成功模拟了我输入的 return 值。但我想模拟的响应KubernetesService class.
中的行 self.api_instance.list_namespace()
有人有想法吗?
在您的示例中,您尝试修补 class (api_instance
) 的实例属性。这不能通过仅从 class 引用它来完成,因为它不是 class 属性 - 您需要一个实例。
通常有两种标准方法来模拟实例属性:
- mock 整个 class,在这种情况下,mock 的 class 上的
return_value
属性将是一个替换 class 的任何实例的 mock,因此可以用于模拟实例属性
- 使用 mock.patch.object 或类似方法模拟具体实例 - 这要求您可以访问测试中的实例
模拟整个 class 在您的情况下不是一个选项,因为您需要使用 class 的功能,但是因为您可以通过 self.service
访问实例, 您可以使用 patch.object
:
def test_get_namespaces(self):
self.service = KubernetesService()
with mock.patch.object(self.service.api_instance, 'list_namespace',
return_value=utils.kubernetes_namespaces_response()):
actual_result = self.service.get_namespaces()
assert actual_result == ['default', 'kube-node-lease', 'kube-public', 'kube-system']
我想模拟来自 Python Kubernetes 客户端的响应。下面是我的 Kubernetes 服务的代码:
import os
from kubernetes.client.rest import ApiException
from kubernetes import client
from kubernetes.config import load_config
from exceptions.logs_not_found_exceptions import LogsNotFound
import logging
log = logging.getLogger("services/kubernetes_service.py")
class KubernetesService:
def __init__(self):
super().__init__()
if os.getenv("DISABLE_KUBERNETES_CONFIG") == "False":
load_config()
self.api_instance = client.CoreV1Api()
def get_namespaces(self):
try:
api_response = self.api_instance.list_namespace()
dict_response = api_response.to_dict()
namespaces = []
for item in dict_response['items']:
namespaces.append(item['metadata']['name'])
log.info(f"Retrieved the namespaces: {namespaces}")
return namespaces
except ApiException as e:
raise e
当我想使用 mock.patch 模拟这个时,我收到了 ModuleNotFoundError。下面是我的测试代码 class
import os
from unittest import mock
from tests.unit_tests import utils
from services.kubernetes_service import KubernetesService
class TestKubernetesService:
@mock.patch.dict(os.environ, {"DISABLE_KUBERNETES_CONFIG": "True"})
def test_get_namespaces(self):
self.service = KubernetesService()
print(self.service.api_instance)
with mock.patch('services.kubernetes_service.KubernetesService.api_instance.list_namespace',
return_value=utils.kubernetes_namespaces_response()):
actual_result = self.service.get_namespaces()
assert actual_result == ['default', 'kube-node-lease', 'kube-public', 'kube-system']
当我将 mock.patch
中的路径从 services.kubernetes_service.KubernetesService.api_instance.list_namespace
编辑到 services.kubernetes_service.KubernetesService.get_namespaces
时,它成功模拟了我输入的 return 值。但我想模拟的响应KubernetesService class.
self.api_instance.list_namespace()
有人有想法吗?
在您的示例中,您尝试修补 class (api_instance
) 的实例属性。这不能通过仅从 class 引用它来完成,因为它不是 class 属性 - 您需要一个实例。
通常有两种标准方法来模拟实例属性:
- mock 整个 class,在这种情况下,mock 的 class 上的
return_value
属性将是一个替换 class 的任何实例的 mock,因此可以用于模拟实例属性 - 使用 mock.patch.object 或类似方法模拟具体实例 - 这要求您可以访问测试中的实例
模拟整个 class 在您的情况下不是一个选项,因为您需要使用 class 的功能,但是因为您可以通过 self.service
访问实例, 您可以使用 patch.object
:
def test_get_namespaces(self):
self.service = KubernetesService()
with mock.patch.object(self.service.api_instance, 'list_namespace',
return_value=utils.kubernetes_namespaces_response()):
actual_result = self.service.get_namespaces()
assert actual_result == ['default', 'kube-node-lease', 'kube-public', 'kube-system']