[英]Unittest.mock - how to mock a call to cursor.execute() from connection object?
I am trying to stub out cursor.execute() in the following code with mock such that I can test execute is called with a correctly formatted query:我正在尝试使用模拟在以下代码中存根 cursor.execute() 以便我可以测试使用格式正确的查询调用 execute :
// Module ABC
def buildAndExecuteQuery( tablesAndColumnsToSelect ):
'''Build and execute a query.
Args: tablesAndColumnsToSelect (dict)
- keys are table names, values are columns
'''
query = ..... < logic to build query > ....
from django.db import connections
cursor = connections[ 'mydb' ].cursor()
cursor.execute( query )
How can I accomplish this type of mock in python2.7 with the mock library?如何使用模拟库在 python2.7 中完成这种类型的模拟?
I will expand @G_M answer with example since I have two objections:我将用例子扩展@G_M 答案,因为我有两个反对意见:
mock
we should not patch objects where they are defined:mock
我们不应该在定义对象的地方修补它们:The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.
基本原则是在查找对象的位置打补丁,该位置不一定与定义的位置相同。 A couple of examples will help to clarify this.
几个例子将有助于澄清这一点。
Ref: https://docs.python.org/3/library/unittest.mock.html#where-to-patch参考: https : //docs.python.org/3/library/unittest.mock.html#where-to-patch
Example:例子:
Our function we want to test:我们要测试的函数:
# foooo_bar.py
from typing import Optional
from django.db import DEFAULT_DB_ALIAS, connections
def some_function(some_arg: str, db_alias: Optional[str] = DEFAULT_DB_ALIAS):
with connections[db_alias].cursor() as cursor:
cursor.execute('SOME SQL FROM %s;', [some_arg])
Test:测试:
# test_foooo_bar.py
from unittest import mock
from django.db import DEFAULT_DB_ALIAS
from django.test import SimpleTestCase
from core.db_utils.xx import some_function
class ExampleSimpleTestCase(SimpleTestCase):
@mock.patch('foooo_bar.connections')
def test_some_function_executes_some_sql(self, mock_connections):
mock_cursor = mock_connections.__getitem__(DEFAULT_DB_ALIAS).cursor.return_value.__enter__.return_value
some_function('fooo')
# Demonstrating assert_* options:
mock_cursor.execute.assert_called_once()
mock_cursor.execute.assert_called()
mock_cursor.execute.assert_called_once_with('SOME SQL FROM %s;', ['fooo'])
Since I don't know what your query logic is, I modified the query
to just accept a sentinel value directly through the tables_and_columns_to_select
argument.由于我不知道您的查询逻辑是什么,我将
query
修改为仅通过tables_and_columns_to_select
参数直接接受哨兵值。
# b_and_ex_q.py
def build_and_execute_query(tables_and_columns_to_select):
"""Build and execute a query.
Args: tablesAndColumnsToSelect (dict)
- keys are table names, values are columns
"""
query = tables_and_columns_to_select # ..... < logic to build query > ....
from django.db import connections
cursor = connections['mydb'].cursor()
cursor.execute(query)
import unittest
from mock import patch, sentinel
from b_and_ex_q import build_and_execute_query
class TestCursorExecute(unittest.TestCase):
@patch('django.db.connections')
def test_build_and_execute_query(self, mock_connections):
# Arrange
mock_cursor = mock_connections.__getitem__('mydb').cursor.return_value
# Act
build_and_execute_query(sentinel.t_and_c)
# Assert
mock_cursor.execute.assert_called_once_with(sentinel.t_and_c)
if __name__ == '__main__':
unittest.main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.