首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用pytest-mock模拟方法

无法使用pytest-mock模拟方法
EN

Stack Overflow用户
提问于 2022-06-17 16:05:53
回答 1查看 54关注 0票数 0

我有一个“MyClass”类,代码如下所示。

代码语言:javascript
复制
class MyClass:

    def __init__(update_type_id='1')
        
        self.update_type_id = update_type_id
        self._cursor = <database_connection).cursor()

    def update_start_dt(self):
        self._update_job_ctrl_start_dt()
        
    def _update_job_ctrl_start_dt(self):
        update_sql, v_1  = self._get_update_sql(self._update_type_id)
        logger.debug(f'Update sql: {update_sql} and v_1: {v_1}')
                
    def _get_update_sql(self, update_type_id: int) -> Tuple:
        sql = f"SELECT start_sql, end_sql FROM <database.table> where update_type_key = {self._update_type_id}"
        self._run_sql(sql)
        record = self._cursor.fetchone()
        if record:
            return record
        else:
            logger.error(f'Record Not Found. Update type key ({update_type_id}) not found in the table in the database')
            raise Exception


    def _run_sql(self, sql_statement: str):
        try:
            self._cursor.execute(sql_statement)
        except (Exception, Error) as e:
            logger.error(f'Error {e} encountered when reading from table')
            raise e

我正在尝试使用pytest-mock编写一个测试函数,这将测试update_start_dt方法。该方法在内部调用一系列私有方法,我很难模拟贯穿所有私有方法的代码。有人能帮我弄明白我们能用什么方式嘲笑吗?

我试图参考多个在线网站,但无法得到一个完整的图片。

代码语言:javascript
复制
class TestMyClass:
    
    def test_update_start_dt(mocker,mock_get_connection,mock_run_sql):
    
        mock_manager = mocker.Mock()
        mock_get_update_sql = mock_manager.patch('MyClass._get_update_sql')
        mock_get_update_sql.return_value = ('123','234')
        myclass = MyClass(update_type_id='1')
        
        myclass.update_start_dt()

以上测试代码的错误如下所示

代码语言:javascript
复制
update_sql, v_1  = self._get_update_sql(self._update_type_id)
ValueError: not enough values to unpack (expected 2, got 0)
EN

回答 1

Stack Overflow用户

发布于 2022-06-18 12:37:55

这里的问题是,您正在对正在创建的Mock对象进行修补,为了测试的目的,您不需要显式地创建Mock对象。下面展示了如何测试它,我们直接在类上进行patch测试。

代码语言:javascript
复制
class MyClass:

    def __init__(self, update_type_id='1'):
        
        self._update_type_id = update_type_id
        self._cursor = None

    def update_start_dt(self):
        self._update_job_ctrl_start_dt()
        
    def _update_job_ctrl_start_dt(self):
        update_sql, v_1  = self._get_update_sql(self._update_type_id)
        logger.debug(f'Update sql: {update_sql} and v_1: {v_1}')
                
    def _get_update_sql(self, update_type_id: int):
        sql = f"SELECT start_sql, end_sql FROM <database.table> where update_type_key = {self._update_type_id}"
        self._run_sql(sql)
        record = self._cursor.fetchone()
        if record:
            return record
        else:
            logger.error(f'Record Not Found. Update type key ({update_type_id}) not found in the table in the database')
            raise Exception


    def _run_sql(self, sql_statement: str):
        try:
            self._cursor.execute(sql_statement)
        except (Exception, Error) as e:
            logger.error(f'Error {e} encountered when reading from table')
            raise e



def test_update_start_dt(mocker):
    mock_get_update_sql = mocker.patch.object(MyClass, "_get_update_sql")
    mock_get_update_sql.return_value = ("123", "234")
    myclass = MyClass(update_type_id='1')

    myclass.update_start_dt()

代码语言:javascript
复制
=========================================== test session starts ============================================
platform darwin -- Python 3.8.9, pytest-7.0.1, pluggy-1.0.0
rootdir: ***
plugins: mock-3.7.0
collected 1 item                                                                                           

test_script.py .                                                                                     [100%]

======================================= 1 passed, 1 warning in 0.01s =======================================

如果调用创建的Mock对象而不是类,代码就会工作。如下所示。

代码语言:javascript
复制
def test_update_start_dt(mocker):
    mock_manager = mocker.Mock()
    mock_get_update_sql = mock_manager.patch('MyClass._get_update_sql')
    mock_get_update_sql.return_value = ('123','234')
    # Notice how we use `mock_manager` instead of MyClass
    # tests will now pass
    myclass = mock_manager(update_type_id='1')
    
    myclass.update_start_dt()

希望你能看到现在的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72662060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档