为啥我的单元测试因错误“str”对象没有属性“光标”而失败?

Posted

技术标签:

【中文标题】为啥我的单元测试因错误“str”对象没有属性“光标”而失败?【英文标题】:Why is my unittest failing with the error 'str' object has no attribute 'cursor'?为什么我的单元测试因错误“str”对象没有属性“光标”而失败? 【发布时间】:2021-11-03 20:19:10 【问题描述】:

我有代码:

def get_address_query(trader_id, connection):
    cursor = connection.cursor()
    sql_address_data = "SELECT * FROM address where id = '%s' AND type = 'registered'"
    cursor.execute(sql_address_data, trader_id)
    address_query = cursor.fetchall()
    if address_query is None:
        raise Exception("address details do not exist")
    else:
        return address_query

我已经编写了以下测试:

    @mock.patch('lambda_function.pymysql')
    def test_get_address_query(self, mock_database_connection):
        mock_record = (('test',),('first',),('last',))
        mock_database_connection.cursor.return_value.fetchall.return_value = mock_record
        result = lambda_function.get_address_query('test', 'connection')
        self.assertEqual(result, mock_record)

但我遇到以下错误:

id = 'test', connection = 'connection'

    def get_address_query(id, connection):
>       cursor = connection.cursor()
E       AttributeError: 'str' object has no attribute 'cursor'

../lambda_function.py:92: AttributeError

我知道这个错误是由于我没有正确地模拟 connection.cursor.fetchall 但我不确定如何正确地做到这一点。任何帮助将不胜感激。

【问题讨论】:

尝试使用result = lambda_function.get_address_query('test', mock_database_connection) 修复行result = lambda_function.get_address_query('test', 'connection')。但之后可能还有一些错误需要修复。 【参考方案1】:

您将字符串 'connection' 作为第二个参数传递给 get_address_query()

lambda_function.get_address_query('test', 'connection')

然后在get_address_query() 中,它使用第二个参数connection(它是一个字符串)调用方法.cursor()

def get_address_query(trader_id, connection):
    cursor = connection.cursor()
    ...

所以这就像调用'connection'.cursor() 显然会失败,因为str 没有这样的方法。

相反,您需要做的是将模拟对象 mock_database_connection 传递给 connection 参数。这样一来,所有对connection 的调用(例如connection.cursor())都将使用配置的模拟对象。

这是您可能希望用作参考的最小测试代码:

import unittest
from unittest import mock


def get_address_query(trader_id, connection):
    cursor = connection.cursor()
    sql_address_data = "SELECT * FROM address where id = '%s' AND type = 'registered'"
    cursor.execute(sql_address_data, trader_id)
    address_query = cursor.fetchall()
    if address_query is None:
        raise Exception("address details do not exist")
    else:
        return address_query


class TestSample(unittest.TestCase):
    def test_get_address_query(self):
        mock_database_connection = mock.MagicMock()

        mock_record = (('test',),('first',),('last',))
        mock_database_connection.cursor.return_value.fetchall.return_value = mock_record

        result = get_address_query('test', mock_database_connection)

        self.assertEqual(result, (mock_record))


if __name__ == '__main__':
    unittest.main()

输出:

$ python3 test_src.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
现在,cursor.fetchall() 的响应与我们在模拟对象 mock_database_connection 中配置的一样。

【讨论】:

以上是关于为啥我的单元测试因错误“str”对象没有属性“光标”而失败?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 pytest 在测试模型创建时会抛出“AttributeError:'NoneType'对象没有属性'_meta'”错误?

为啥没有用户代理为视频元素实现 CSS 光标样式

为啥在这个单元测试中没有调用 finalize 函数?

PyMySQL 错误:“str”对象没有属性“to_sql”

outlook发送邮件为啥老显示错误

为啥 ApplicationsDocumentsDirectory 为单元测试返回 null?