我有一个关于如何模拟嵌套方法并测试它被调用的问题。我很难理解:https ://docs.python.org/3/library/unittest.mock-examples.html#mocking-chained-calls 。
我想测试一下这个类中的 deploy_file 方法是否调用了 fabric 库中的“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 对象时收到与“host”参数相关的错误。
我认为当调用“conn.put”时,它会创建一个全新的 Mock 对象,并且在 unittest 运行时我没有测试该对象。我只是不确定如何定义测试来实际测试 put 的调用。
我也是了解要测试什么(以及如何测试)和不测试什么以及如何使用模拟等方面的新手。不过,我完全接受了这个想法。在我从事项目工作时,发现错误和回归非常有帮助。