我将用示例扩展@G_M 答案,因为我有两个反对意见:
- 在我看来,显式关闭数据库游标是一种很好的做法,更多信息请参见:显式 cursor.close() 的必要性。这可以通过将光标用作上下文管理器来完成,更多内容在 Django 文档中:https ://docs.djangoproject.com/en/dev/topics/db/sql/#connections-and-cursors 。
- 使用时,
mock
我们不应该修补定义它们的对象:
基本原则是您在查找对象的位置进行修补,该位置不一定与定义对象的位置相同。几个例子将有助于澄清这一点。
参考:https ://docs.python.org/3/library/unittest.mock.html#where-to-patch
例子:
我们要测试的功能:
# 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_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'])