我有一个关于如何模拟嵌套方法并测试其调用方式的问题。我很难理解:https://docs.python.org/3/library/unittest.mock-examples.html#mocking-chained-calls。
我想测试结构类库中的deploy_file方法调用了结构库中的“ put”方法,以及可能为其指定了什么值。该模块从AWS收集一些信息,并提供一种对数据采取操作的方法。
import json
import os
from aws.secrets_manager import get_secret
from fabric import Connection
class Deploy:
def __init__(self):
self.secrets = None
self.set_secrets()
def set_secrets(self):
secrets = get_secret()
self.secrets = json.loads(secrets)
def deploy_file(self, source_file):
with Connection(host=os.environ.get('SSH_USERNAME'), user=os.environ.get("SSH_USERNAME")) as conn:
destination_path = self.secrets["app_path"] + '/' + os.path.basename(source_file)
conn.put(source_file, destination_path)
“ get_secret”是另一个模块中的一种方法,该模块使用boto3库从AWS获取信息。
这些是我正在从事的测试:
from unittest.mock import patch
from fabric import Connection
from jobs.deploy import Deploy
def test_set_secrets_dict_from_expected_json_string():
with patch('jobs.deploy.get_secret') as m_get_secret:
m_get_secret.return_value = '{"app_path": "/var/www/html"}'
deployment = Deploy()
assert deployment.secrets['app_path'] == "/var/www/html"
def test_copy_app_file_calls_fabric_put():
with patch('jobs.deploy.get_secret') as m_get_secret:
m_get_secret.return_value = '{"app_path": "/var/www/html"}'
deployment = Deploy()
with patch('jobs.deploy.Connection', spec=Connection) as m_conn:
local_file_path = "/tmp/foo"
deployment.deploy_file(local_file_path)
m_conn.put.assert_called_once()
其中第二项测试导致“ AssertionError:预期'put'被调用一次。被调用0次。”
第一个测试可以很好地模拟“ get_secret”功能,以测试“ Deploy”的构造函数是否从伪造的AWS数据中设置了“ Deploy.secrets”。
在第二个测试中,像以前一样模拟了get_secrets,并且从结构库中模拟了“ Connection”。如果不模拟Connection,则在创建Connection对象时会收到与“主机”参数有关的错误。
我认为,当调用“ conn.put”时,它会创建一个全新的Mock对象,而当unittest运行时,我不会测试该对象。我只是不确定如何定义测试以实际测试放置请求。
我还是一个了解如何测试(以及如何测试)和不测试什么以及如何使用模拟等的新手。我完全同意这个想法。在我从事项目时发现错误和回归非常有帮助。