使用pyTest Mock对象测试get_user_by_username函数时遇TypeError问题求解
问题与解决方案
待测试函数
def get_user_by_username(db, username: str) -> Waiter: """根据给定用户名获取用户对象。""" user = db.query(Waiter).filter(Waiter.username == username).first() return user
错误的测试代码及报错
我尝试Mock数据库调用并返回正确的Waiter对象,编写的测试代码如下:
def test_get_user_by_username(mocker): waiter = Waiter(id=10, username="string", password="1111") db_mock = mocker.Mock(return_value=waiter) result = get_user_by_username(db=db_mock, username="string") assert result.json()["username"] == "string"
运行时出现错误:TypeError: 'Mock' object is not subscriptable
正确解决方案
根据@Don Kirkby的回答,正确的测试代码如下:
def test_get_user_by_username(mocker): waiter = Waiter(id=10, username="string", password="1111") # 逐层Mock链式调用的每个方法 filter_method = mocker.Mock() filter_method.first = mocker.Mock(return_value=waiter) query = mocker.Mock() query.filter = mocker.Mock(return_value=filter_method) db_mock = mocker.Mock() db_mock.query = mocker.Mock(return_value=query) result = get_user_by_username(db=db_mock, username="string") # 直接通过对象属性或vars()获取属性值做断言 assert vars(result)["username"] == "string" # 也可以直接断言属性:assert result.username == "string"
错误原因说明
- Mock对象不符合链式调用逻辑:原函数中是
db.query(...).filter(...).first()的链式调用,直接给db_mock设置return_value无法模拟这一串方法调用,必须逐层Mock每个方法的返回值,让调用链能正确走到first()并返回预设的Waiter对象。 - 断言方式错误:Waiter对象通常没有
json()方法,即便有,原代码中得到的result可能还是Mock对象而非真实Waiter实例,导致后续下标访问报错。正确做法是直接访问对象属性,或用vars(result)获取属性字典后取值断言。
内容的提问来源于stack exchange,提问作者Vitalii Mytenko
相关产品推荐
相关产品推荐

