Python单元测试断言scoped_session.commit()调用失败问题求助
Python单元测试断言scoped_session.commit()调用失败问题
场景与代码
我编写Python单元测试时,尝试断言scoped_session的.commit()方法被调用,但测试失败。相关代码如下:
main.py
from database import DBSession def deactivate_user(user_id): db_session = DBSession() user = User(db_session).get(user_id) user.is_active = False db_session.commit() def get_account(user_id): pass
database.py
from sqlalchemy.orm import sessionmaker, scoped_session import settings session_factory = sessionmaker(bind=create_engine(settings.CONNECTION_STRING)) DBSession = scoped_session(session_factory)
unit_test.py
from main import deactivate_user def test_deactivate_user(mocker): mocked_account = mocker.patch('main.get_account', return_value=get_test_account()) mocked_session = mocker.patch('database.DBSession', autospec=True) deactivate_user(123) mocked_account.assert_called() mocked_session.commit.assert_called()
错误信息
mocked_account.assert_called()执行正常,但mocked_session.commit.assert_called()失败,报错:
E AssertionError: Expected 'commit' to have been called.
额外调试信息:
type(mocked_session) == <class 'unittest.mock.MagicMock'> mocked_session.mock_calls == []
问题原因与解决办法
核心问题
- Patch位置错误:Python的mock遵循「使用位置优先」原则,你需要patch被测试代码(
main.py)中实际导入使用的DBSession,而非定义它的database.py模块。 - 误解scoped_session的调用逻辑:
DBSession是会话工厂,调用DBSession()才会返回实际的会话实例,commit()是这个实例的方法,而非工厂本身的方法。
修改后的测试代码
from main import deactivate_user def test_deactivate_user(mocker): # Mock get_account mocked_account = mocker.patch('main.get_account', return_value=get_test_account()) # 1. 创建mock会话实例,它才是拥有commit方法的对象 mock_session_instance = mocker.Mock() # 2. Patch main里的DBSession,让它返回这个mock实例 mocked_db_session = mocker.patch('main.DBSession', return_value=mock_session_instance) # 3. Mock User类及其get方法,避免依赖真实数据库操作 mock_user = mocker.Mock(is_active=True) mocked_user_class = mocker.patch('main.User', return_value=mocker.Mock(get=lambda x: mock_user)) deactivate_user(123) # 验证各个调用 mocked_account.assert_called() mocked_db_session.assert_called_once() # 验证DBSession()被调用 mock_session_instance.commit.assert_called_once() # 验证会话实例的commit被调用 assert mock_user.is_active is False # 额外验证用户状态被修改
内容的提问来源于stack exchange,提问作者user7692855
相关产品推荐
相关产品推荐

