2016-08-04 64 views
0

我目前正在写一个单元测试以下get_can_edit功能在我的串行:Django的REST框架 - 单元测试错误

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正确执行,并没有问题,“用户”是客体可调用。

我原本以为我创建的假数据的格式有问题(我使用factory_boyRequestFactory来创建假数据)。使用调试器,我通过调用测试并通过服务器发出真正的请求来进入get_can_edit函数。在这两种情况下,request.userobj.admin是在正确的形式,所以我排除了数据格式错误。

接下来,我在调试器试图

User.objects.get(username=request.user) 

。它对服务器中的真实请求起作用,并且在测试中返回与假请求相同的'User' object is not callable错误。我做了一个快速堆栈溢出/谷歌搜索在Django object is not callable错误,但它看起来像其他情况下,通过确保模型正确,导入(我是绝对正确导入)得到了解决。

所以在这一点我知道,有一个与我的测试情况下一个问题,即不与实际要求存在,但我真的不能弄清楚它是什么,我跑出来的想法。

全码:

The serializer

The test

非常感谢,让我知道,如果有去了解这样的一个更简单的方法。



UPDATE: 于是我又回到了两种不同的调试器,做User.objects.all()。具有真实请求的服务器中的用户返回了正确的用户列表。与虚假请求测试中的那个人刚刚返回anonymoususer。因为我使用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没有作出真正的请求

+1

您正在使用'app.models.User'和'django.contrib.auth.model.User'。这是什么原因?你还可以发布相关模型吗? –

+0

他们是相同的模型...我不知道他们为什么导入不同(我不是这些网页上的唯一合作者),但我只是试着改变他们导入的方式,同样的问题。 用户模型文档位于:https://docs.djangoproject.com/en/1.9/topics/auth/default/ – Tom

回答

1

正是在这里解决:需要Django REST Framework - Fake objects for unit tests

基本上factory_boy工厂进行不同的设置。当我定义我的工厂,我有以下行:

class UserFactory(factory.Factory): 

但很显然,而非factory.Factory,它应该说factory.DjangoModelFactory像这样:

class UserFactory(factory.DjangoModelFactory): 

这是一个有点讨厌,因为factory_boydocumentationfactory.Factory的第一页上的示例,但稍后会告诉您使用DjangoModelFactory。我想这就是我不应该彻底阅读文档所应得的。

2

这是更好,以便在所有测试中使用它来创建一个基类。此类还包含支持HTTP方法的APIClient DRF类,并且您不需要手动创建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