You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

首次运行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()

报错原因分析

  1. Fixture返回值为空:你定义的add_and_delete_database_try fixture没有return语句,默认返回None。当你在测试函数里尝试像调用普通函数一样执行add_and_delete_database_try(new_user)时,本质是在调用None(new_user),直接触发TypeError——None不是可调用对象。
  2. Fixture执行逻辑误解:pytest fixture的作用是在测试用例运行前后自动执行预设逻辑,而非作为函数在测试内部调用。你原本的fixture已经依赖new_user,会在测试用例执行前自动完成数据库的添加和删除操作,测试里重复调用属于逻辑冗余,还因为fixture返回None导致报错。
  3. 修改后的代码修复了问题:将数据库操作逻辑移到测试函数内部后,直接执行操作代码,不再尝试调用返回None的fixture,因此不会触发类型错误。

补充你注释里的疑问:rollback是回滚当前会话中未提交的所有数据库操作,回到上一次提交的状态;delete+commit是主动删除已提交到数据库的记录并确认修改,两者适用场景不同——操作出错未提交时用rollback,需要移除已提交的记录时用delete+commit。

内容的提问来源于stack exchange,提问作者kihnihih

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:54:22