调用pytest fixture时出现TypeError:'Response'对象不可调用问题
问题分析与解决方案
问题根源
- fixture返回的是Response对象而非可调用函数:你定义的
get_requestfixture在被pytest实例化时,会直接执行内部的GET请求并返回requests.Response对象。测试函数中get_request(test_url + '/endpoint')试图把这个Response对象当作函数调用,必然触发TypeError: 'Response' object is not callable错误。 - fixture逻辑存在bug:代码中用了
elif params is None,这意味着只有当headers为None时才会检查params。如果headers不为空但params为None,params会保持None值,后续传给requests.get时可能引发异常。
解决方案
根据你的需求,分两种场景处理:
场景1:希望fixture是可复用的请求工具(推荐)
修改conftest.py中的fixture,让它返回一个可调用的内部函数,而不是直接执行请求:
@pytest.fixture() def get_request(): def _get_request(url=base_url, headers=None, params=None): # 修复逻辑bug:用if替代elif if headers is None: headers = {} if params is None: params = {} session = requests.Session() response = session.get( url=url, headers=get_token(), params=params, verify=False, ) return response # 返回内部函数,让测试函数可以调用它传入参数 return _get_request
测试函数无需修改,此时get_request是一个可调用的函数,执行后返回对应URL的Response对象:
import pytest import requests def test_get_request2(get_request): response = get_request(test_url + '/endpoint') # 后续可以断言response的状态码、响应体等 assert response.status_code == 200
场景2:希望fixture直接返回指定请求的Response
如果不需要动态传参,而是让fixture直接返回特定请求的结果,可以通过pytest的参数化机制实现:
修改conftest.py:
@pytest.fixture() def get_request(request): # 从request.param中获取测试用例传入的参数 req_params = request.param or {} url = req_params.get('url', base_url) headers = req_params.get('headers', {}) params = req_params.get('params', {}) session = requests.Session() response = session.get( url=url, headers=get_token(), params=params, verify=False, ) return response
测试函数通过@pytest.mark.parametrize传参,并设置indirect=True让pytest把参数传给fixture:
import pytest import requests @pytest.mark.parametrize( 'get_request', [{'url': test_url + '/endpoint'}], # 传入请求的URL参数 indirect=True # 告诉pytest将参数传递给fixture处理 ) def test_get_request2(get_request): # 此时get_request就是目标URL的Response对象,直接使用 assert get_request.status_code == 200
内容的提问来源于stack exchange,提问作者K Ʌ Z E
相关产品推荐
相关产品推荐

