我目前正在为序列化程序中的以下get_can_edit
函数编写单元测试:
def get_can_edit(self, obj):
request = self.context.get('request')
user = User.objects.get(username=request.user)
return user == obj.admin
在我的测试中,我在这里调用函数:
def test_get_can_edit(self):
self.request1 = RequestFactory().post('./fake_path')
self.request1.user = SimpleLazyObject(self.user1)
self.request1.query_params = {}
self.serializer1 = ConferenceSerializer(context={'request': self.request1})
self.canEdit1 = self.serializer1.get_can_edit(self.conference)
当我运行测试时,它失败了错误:'User' object is not callable
,并引用了序列化程序get_can_edit
函数中的以下行:
user = User.objects.get(username=request.user)
但是,在浏览器中运行时,get_can_edit函数可以正常执行,并且“用户”功能没有问题。 objet可以赎回。
我最初认为我正在创建的假数据格式存在问题(我使用factory_boy和RequestFactory来创建虚假数据)。使用调试器,我通过调用测试进入get_can_edit函数,并通过发出实际请求通过服务器。在这两种情况下,request.user
和obj.admin
的格式都是正确的,因此我排除了数据格式错误。
接下来,我试过
User.objects.get(username=request.user)
在调试器中。它适用于服务器中的实际请求,并在测试中为假请求返回了相同的'User' object is not callable
错误。我在Django中对object is not callable
错误进行了快速堆栈溢出/谷歌搜索,但看起来其他案例都是通过确保正确导入模型来解决的(我的版本肯定是正确导入的)。
所以在这一点上我知道我的测试用例存在问题,而实际请求并不存在,但我无法弄清楚它是什么,我正在运行没有想法。
完整代码:
非常感谢,如果有更简单的方法,请告诉我。
更新:
所以我回到了两个不同的调试器并做了User.objects.all()
。服务器中具有实际请求的那个返回了正确的用户列表。测试中的虚假请求刚刚返回匿名用户。因为我使用factory_boy创建我的假用户,所以django无法在User.objects
中找到它。
我被告知不要在我的单元测试中提出真正的请求,因此创建一个真正的用户是不可能的。
我还尝试将get_can_edit
功能更改为不检查User.objects.
。 request.user
是包含用户的SimpleLazyObject
。我尝试做的是request.user.id
并将其与obj.admin.id
进行比较,但显然当你对SimpleLazyObject
执行任何操作时,它会咨询User.objects
以获取与实际用户关联的内容有了它,所以它仍然有同样的错误'User' object is not callable
。
所以最重要的是:我需要在User.objects
添加虚假用户而不提出真实请求
答案 0 :(得分:2)
创建基类以便在所有测试中使用它更好。此类也从APIClient
DRF类扩展,它支持HTTP方法,您不需要手动创建Request
个对象。
from rest_framework.test import APITestCase
class BaseAPITestCase(APITestCase):
"""
Base class to initialize the test cases
"""
self.user = YourUserFactory.create_batch(1)
self.user_client = self.get_client(user=self.user)
在你的测试中
class YourTestClass(BaseAPITestCase):
def test_get_can_edit(self):
response = self.user_client.post('./fake_path')
# proccess your response
答案 1 :(得分:1)
这里解决了:Django REST Framework - Fake objects for unit tests
基本上factory_boy
工厂需要以不同的方式设置。在我定义工厂的地方,我有以下几行:
class UserFactory(factory.Factory):
但显然不是factory.Factory
,而是应该factory.DjangoModelFactory
这样说:
class UserFactory(factory.DjangoModelFactory):
这有点令人讨厌,因为factory_boy
documentation在第一页上有factory.Factory
的示例,但稍后会告诉您使用DjangoModelFactory
。我想这是我没有彻底阅读文档所应得的。