Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock object is not iterable

I am currently trying (and failing) to perform unit tests on my simple app which posts data to a MySQL database. Below is the unit test I am trying to run, not sure if this will eve test my code successfully, but is coming up with a 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

Any helps is greatly appreciated

like image 795
L Thompson Avatar asked Dec 24 '22 02:12

L Thompson


2 Answers

When you create a mock, you sometimes have to let it know how to respond to some of the calls that will be expected of it. Take, for example:

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

If you were to create a Mock to use in place of an instance of A, the mock wouldn't automagically know how to respond if you attempt to request .items. You can overcome this by telling the Mock what to return for a particular property by passing that as a keyword to the constructor, like so:

mocked_a = Mock(items = [])

Now, when you call mock_a.items you'll get an empty list, so iteration won't fault.

like image 52
g.d.d.c Avatar answered Dec 25 '22 14:12

g.d.d.c


To make mock iterable you need to mock its __iter__ method. For example:

cursor = Mock()
cursor.__iter__.return_value = []
like image 31
Vladimir Prudnikov Avatar answered Dec 25 '22 15:12

Vladimir Prudnikov