Django DRF TestCase中pytest fixture调用报错及正确用法咨询
问题核心原因
你遇到的报错本质是混用了pytest fixture机制与Django原生unittest风格的TestCase,同时fixture的使用逻辑存在偏差:
- 用
rf.get()报错:你将fixture函数本身作为参数默认值传入,此时rf指向的是a_api_request_factory函数对象,不是fixture返回的APIRequestFactory实例,函数自然不存在get属性。 - 用
rf()报错:pytest fixture设计上不允许直接调用,fixture的返回值需要由pytest自动注入,手动调用fixture函数会触发规则校验报错。
解决方案
方案1:全量切换为pytest风格测试(推荐)
弃用Django自带的TestCase类,pytest会自动将fixture返回值注入到测试函数的参数中,不需要手动处理实例化逻辑:
import pytest from rest_framework.test import APIRequestFactory from your_app.views import userprofile_detail_view # fixture定义保持不变,返回的是APIRequestFactory实例 @pytest.fixture def a_api_request_factory(): return APIRequestFactory() # 假设a_user_profile fixture你已经正确定义 @pytest.fixture def a_user_profile(): # 生成UserProfile实例的逻辑 ... # 开启数据库访问权限,测试用函数式写法,参数直接声明依赖的fixture @pytest.mark.django_db def test_create_userprofile(up=a_user_profile, rf=a_api_request_factory): """测试用户详情视图返回正常""" # rf已经是fixture返回的实例,直接调用get方法即可 request = rf.get('/api/userprofile/') request.user = up.user response = userprofile_detail_view(request) assert response.status_code == 200 assert response.data['user'] == up.user.username
如果需要保留类式写法,不要继承unittest的TestCase即可:
@pytest.mark.django_db class TestUserProfileDetailView: def test_create_userprofile(self, up=a_user_profile, rf=a_api_request_factory): request = rf.get('/api/userprofile/') request.user = up.user response = userprofile_detail_view(request) assert response.status_code == 200 assert response.data['user'] == up.user.username
方案2:保留unittest风格测试
如果不想切换pytest写法,直接用setUp方法替代fixture做初始化,不需要引入pytest fixture:
from django.test import TestCase from rest_framework.test import APIRequestFactory from your_app.views import userprofile_detail_view from your_app.models import UserProfile class TestUserProfileDetailView(TestCase): def setUp(self): # 所有测试共用的初始化逻辑,替代fixture作用 self.rf = APIRequestFactory() # 生成UserProfile测试实例 self.up = UserProfile.objects.create(...) def test_create_userprofile(self): request = self.rf.get('/api/userprofile/') request.user = self.up.user response = userprofile_detail_view(request) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['user'], self.up.user.username)
避坑规范
- 不要混用pytest fixture和unittest风格的TestCase:如果用Django原生
TestCase,就用setUp/tearDown做初始化;如果用pytest fixture,全程用pytest风格的测试写法,不要继承unittest的TestCase类。 - fixture的核心逻辑是声明依赖即可,pytest自动注入实例,不需要手动调用fixture函数,也不需要加括号获取返回值。
- 工厂类使用要明确层级:类似
APIRequestFactory这种工厂类,加括号调用得到实例,实例才有get/post等请求方法。
内容的提问来源于stack exchange,提问作者Back2Basics
相关产品推荐
相关产品推荐

