首次运行test_verified_email报TypeError: NoneType不可调用的原因
问题:
test_verified_email 报错 TypeError: 'NoneType' object is not callable 的原因 报错场景
首次运行测试代码时,test_verified_email 用例抛出 TypeError: 'NoneType' object is not callable 错误;将数据库操作逻辑从独立fixture移到测试函数内部后,运行恢复正常。
首次出错的代码
conftest.py
@pytest.fixture() def new_user(): # why can't I go plaintext_password() instead of plaintext_password plaintext_password = 'pojkp[kjpj[pj' hashed_password = bcrypt.hashpw(plaintext_password.encode('utf-8'), bcrypt.gensalt()) current_user = User(username='fkpr[kfkuh', hashed_password=hashed_password, email=os.environ['TESTING_EMAIL_USERNAME'], confirmation_email=False, reset_email_password=False) return current_user
test_routes.py(出错版本)
@pytest.fixture() def add_and_delete_database_try(new_user): try: db.session.add(new_user) db.session.commit() db.session.delete(new_user) db.session.commit() except: # what does rollback do vs delete and commit? db.session.rollback() def test_verified_email(token_client, new_user, add_and_delete_database_try): response = token_client.get("/verified_email<token>", follow_redirects=True) assert response.status_code == 200 with token_app.test_request_context(): add_and_delete_database_try(new_user)
修改后正常的代码(test_routes.py)
def test_verified_email(token_client, new_user): response = token_client.get("/verified_email<token>", follow_redirects=True) assert response.status_code == 200 with token_app.test_request_context(): try: db.session.add(new_user) db.session.commit() db.session.delete(new_user) db.session.commit() except: db.session.rollback()
报错原因分析
- Fixture返回值为空:你定义的
add_and_delete_database_tryfixture没有return语句,默认返回None。当你在测试函数里尝试像调用普通函数一样执行add_and_delete_database_try(new_user)时,本质是在调用None(new_user),直接触发TypeError——None不是可调用对象。 - Fixture执行逻辑误解:pytest fixture的作用是在测试用例运行前后自动执行预设逻辑,而非作为函数在测试内部调用。你原本的fixture已经依赖
new_user,会在测试用例执行前自动完成数据库的添加和删除操作,测试里重复调用属于逻辑冗余,还因为fixture返回None导致报错。 - 修改后的代码修复了问题:将数据库操作逻辑移到测试函数内部后,直接执行操作代码,不再尝试调用返回
None的fixture,因此不会触发类型错误。
补充你注释里的疑问:rollback是回滚当前会话中未提交的所有数据库操作,回到上一次提交的状态;delete+commit是主动删除已提交到数据库的记录并确认修改,两者适用场景不同——操作出错未提交时用rollback,需要移除已提交的记录时用delete+commit。
内容的提问来源于stack exchange,提问作者kihnihih
相关产品推荐
相关产品推荐

