简体   繁体   English

在单元测试中模拟python类并验证实例

[英]Mocking python class in unit test and verifying an instance

I'm trying to unit test an SFTP helper class that makes some calls to the pysftp module. 我正在尝试对SFTP帮助程序类进行单元测试,该类对pysftp模块进行了一些调用。 I want to mock the actual network calls from pysftp so there are no side effects, and just make sure that the class is correctly calling the underlying SFTP methods with the correct paramaters. 我想模拟来自pysftp的实际网络调用,因此没有副作用,只需确保该类使用正确的参数正确调用了基础SFTP方法。

Here is a simple example of my code so far: 到目前为止,这是我的代码的一个简单示例:

import pysftp
import unittest
import mock

class SFTPHelper(object):
    def __init__(self, host, username, password, files_dir):
        self.host = host
        self.username = username
        self.password = password
        self.files_dir = files_dir

    def list_files(self):
        with pysftp.Connection(
                self.host,
                username=self.username,
                password=self.password) as sftp:
            return sftp.listdir(self.files_dir)

class TestSFTPHelper(unittest.TestCase):
    @mock.patch('pysftp.Connection')
    def test_list_files(self, mock_connection):
        sftp_helper = SFTPHelper('somehost', 'someuser', 'somepassword', '/some/files/dir')
        sftp_helper.list_files()

        # this assertion passes
        mock_connection.assert_called_with(
            'somehost', password='somepassword', username='someuser')

        # this assertion does not pass
        mock_connection.listdir.assert_called_with('/some/files/dir')

The assertion error: 断言错误:

AssertionError: Expected call: listdir('/some/files/dir')
Not called

I assume it doesn't work because I need to assert that the function was called on the instance, but how do I get the instances of pysftp.Connection that was used in my method? 我认为它不起作用,因为我需要断言该函数是在实例上调用的,但是如何获取在我的方法中使用的pysftp.Connection实例呢?

You could configure the mock to return a new mock object with __enter__ and __exit__ methods defined. 您可以配置模拟,以返回定义了__enter____exit__方法的新模拟对象。 For example: 例如:

@mock.patch.object(
    target=pysftp,
    attribute='Connection',
    autospec=True,
    return_value=mock.Mock(
        spec=pysftp.Connection,
        __enter__=lambda self: self,
        __exit__=lambda *args: None
    )
)
def test_list_files(self, mock_connection):
    # (contents of test case)

In addition, you may want to use: 另外,您可能要使用:

mock_connection.return_value.listdir.assert_called_with('/some/files/dir')

instead of: 代替:

mock_connection.listdir.assert_called_with('/some/files/dir')

As a side note, you could also replace both uses of assert_called_with in your example with assert_called_once_with . 作为一个侧面说明,你也可以更换的两种用法assert_called_with在你的榜样assert_called_once_with

The end result: 最终结果:

$ python -m unittest test_sftp_helper.TestSFTPHelper.test_list_files
.
----------------------------------------------------------------------
Ran 1 test in 0.017s

OK

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM