问题描述
我不知道为什么我没有得到这个,但我想在 Python 中使用模拟来测试我的函数是否正确调用了 ftplib.FTP 中的函数.我已经简化了一切,但仍然没有考虑它是如何工作的.这是一个简单的例子:
I don't know why I'm just not getting this, but I want to use mock in Python to test that my functions are calling functions in ftplib.FTP correctly. I've simplified everything down and still am not wrapping my head around how it works. Here is a simple example:
import unittest
import ftplib
from unittest.mock import patch
def download_file(hostname, file_path, file_name):
ftp = ftplib.FTP(hostname)
ftp.login()
ftp.cwd(file_path)
class TestDownloader(unittest.TestCase):
@patch('ftplib.FTP')
def test_download_file(self, mock_ftp):
download_file('ftp.server.local', 'pub/files', 'wanted_file.txt')
mock_ftp.cwd.assert_called_with('pub/files')
当我运行这个时,我得到:
When I run this, I get:
AssertionError: Expected call: cwd('pub/files')
Not called
我知道它必须使用模拟对象,因为这是一个假的服务器名称,并且在不打补丁的情况下运行时,它会抛出socket.gaierror"异常.
I know it must be using the mock object since that is a fake server name, and when run without patching, it throws a "socket.gaierror" exception.
如何获取函数正在运行的实际对象?长期目标不是在同一个文件中包含download_file"函数,而是从单独的模块文件中调用它.
How do I get the actual object the fuction is running? The long term goal is not having the "download_file" function in the same file, but calling it from a separate module file.
推荐答案
当您执行 patch(ftplib.FTP)
时,您正在修补 FTP
构造函数.dowload_file()
使用它来构建 ftp
对象,以便您在其上调用 login()
和 cmd()
将是 mock_ftp.return_value
而不是 mock_ftp
.
When you do patch(ftplib.FTP)
you are patching FTP
constructor. dowload_file()
use it to build ftp
object so your ftp
object on which you call login()
and cmd()
will be mock_ftp.return_value
instead of mock_ftp
.
您的测试代码应遵循:
class TestDownloader(unittest.TestCase):
@patch('ftplib.FTP', autospec=True)
def test_download_file(self, mock_ftp_constructor):
mock_ftp = mock_ftp_constructor.return_value
download_file('ftp.server.local', 'pub/files', 'wanted_file.txt')
mock_ftp_constructor.assert_called_with('ftp.server.local')
self.assertTrue(mock_ftp.login.called)
mock_ftp.cwd.assert_called_with('pub/files')
我添加了所有检查和 autospec=True
只是因为是一个 良好做法
I added all checks and autospec=True
just because is a good practice
这篇关于模拟 ftplib.FTP 用于单元测试 Python 代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!