Mock对象不可迭代。

5

我目前正在尝试对我的简单应用程序进行单元测试,该应用程序将数据发布到MySQL数据库。以下是我尝试运行的单元测试,不确定是否能成功测试我的代码,但会出现TypeError: 'Mock' object is not iterable错误。

Unit_Test.py

from unittest import mock
from unittest.mock import patch, MagicMock
from unittest.mock import Mock


from source.src.scores import *


@mock.patch('source.src.scores.request')
def test_add_scores(self):
    columns = ["Match_ID", "Home_Score", "Away_Score"]
    values = [1, 1, 1]

    expected_score = {columns[i]: values[i] for i in range(len(columns))}

    with patch('source.src.scores.mysql.connector') as patch_connector:

        cursor = Mock()
        cursor.fetchone.return_value = values
        cursor.column_names = columns
        connect = Mock()
        connect.cursor.return_value = cursor

        patch_connector.connect.return_value = connect

        with patch('source.src.scores.jsonify') as json:
            json.return_value = expected_score

            json_return, http_code = add_score()

        assert patch_connector.connect.called
        assert connect.cursor.called
        assert connect.commit.called
        assert cursor.fetchone.called
        self.assertEqual(cursor.execute.call_count, 2)
        self.assertDictEqual(expected_score, json_return)


if __name__ == '__main__':
test_add_scores()

scores.py

 def execute_query(cursor, qry):
print("Executing query...")
cursor.execute(qry)


def execute_query_json(cursor, qry, cnx):
print("Executing JSON query...")
cursor.execute(qry, (request.json['Match_ID'],
                     request.json['Home_Score'],
                     request.json['Away_Score'],
                     )
               )
cnx.commit()


def add_score():
cnx = conn_db()
cursor = cnx.cursor()
print("Updating score")

execute_query_json(cursor, "INSERT INTO scores (Match_ID, Home_Score, Away_Score) VALUES (%s,%s,%s)", cnx)
execute_query(cursor, "SELECT * FROM scores WHERE Score_ID=" + str(cursor.lastrowid))
recs = extract_records(cursor)

return jsonify({'discipline':recs}), 201

任何帮助都非常感激。

尝试指明错误发生的行数。在出现“不可迭代”错误的情况下,通常只是因为我们在应该使用()的地方使用了[]或其他类似的操作符。 - KuboMD
请问您能否提供堆栈跟踪信息? - e.s.
1
无关的,但更喜欢使用{k:v for k, v in zip(columns, values)}(甚至是dict(zip(columns, vertices)))来替代索引迭代。 - chepner
4个回答

9

当你创建一个模拟对象时,有时需要让它知道如何响应它将被期望的一些调用。例如:

class A(object):
  def __init__(self):
    self.items = []

如果您要创建一个Mock来代替A的实例,那么如果您尝试请求.items,Mock将无法自动知道如何响应。您可以通过将特定属性的返回值作为关键字传递给构造函数来告诉Mock如何返回,例如:
mocked_a = Mock(items = [])

现在,当您调用 mock_a.items 时,您将得到一个空列表,因此迭代不会出错。

4
为使模拟对象可迭代,您需要模拟其__iter__方法。例如:
cursor = Mock()
cursor.__iter__.return_value = []

2
错误信息 TypeError: 'Mock' object is not iterable 告诉您,您的模拟对象之一不可迭代:您正在尝试但无法遍历它(for elem in ...)或对其调用 list()。要使对象可迭代,它需要实现 __iter__ 魔术方法(请参见 https://dev59.com/L2435IYBdhLWcg3wtSYV#5262255)。 MagicMock 对象(您在测试中导入)与其他双下划线魔术方法一起 实现了__iter__。您可以尝试将您的 cursorconnect 对象更改为 MagicMock 实例。

2

我尝试了不同的方法,花了一些时间。MagicMock() 对我来说从来没有起作用,但 Magic() 起作用了。谢谢!

这个是有效的:

mocked_a = Mock(items = [])

然后,mocked_a.items 将返回 []

使用 Mock() 的情况下,也不起作用,即使使用 MagicMock() 也不行。无论我如何尝试,都无法将 [] 分配给 cursor!

cursor = Mock()

cursor.__iter__.return_value = []

or:

cursor = MagicMock()

cursor.__iter__.return_value = []


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接