如何在django中模拟用户和请求

Pur*_*ell 69 python django unit-testing mocking

我有与请求对象或用户对象交互的django代码.例如:

foo_model_instance = models.get_or_create_foo_from_user(request.user)
Run Code Online (Sandbox Code Playgroud)

如果您要使用django python shell或单元测试进行测试,那么您会在那里传递什么?这里只是一个User对象,但是对模拟请求对象的需求也经常出现.

对于shell或单元测试:

  • 你如何模仿用户?
  • 你如何模拟请求?

nao*_*oko 74

对于请求,我会使用Django附带的RequestFactory.

from django.test.client import RequestFactory
rf = RequestFactory()
get_request = rf.get('/hello/')
post_request = rf.post('/submit/', {'foo': 'bar'})
Run Code Online (Sandbox Code Playgroud)

对于用户,我会使用django.contrib.auth.models.User作为@ozan建议并且可能与工厂男孩一起提速(与工厂男孩你可以选择不保存到DB)


oza*_*zan 48

你如何模仿用户?

初始化一个django.contrib.auth.models.User对象.User.objects.create_user让这很容易.

你如何模拟请求?

初始化一个django.http.HttpRequest对象.

当然,根据您的想法,有快捷方式.如果您只需要一个具有user指向用户的属性的对象,只需创建一些东西(任何东西)并为其赋予该属性.

  • @ S.Lott我不是说客户端很慢,或者声称模拟比客户端更快(我假设"客户端"你指的是djangos虚拟网络"浏览器").我说他们比DB访问更快(这只适用于这个问题的'User`部分).如果你不认为模拟比实际访问数据库更快,那么我怀疑你没有真正尝试和比较.在一个非常小的项目中,当我们将代码更改为模拟模型时,我们的团队从1.5分钟的测试套件转到<5秒.当差距如此之大时,没有必要编写基准. (11认同)
  • @ S.Lott有时会使用真实的东西,但随着项目的增长,它会变得很慢.能够在几秒钟而不是几分钟内运行模拟测试是很好的. (2认同)

Mic*_*son 7

您可以像Anurag Uniyal所建议的那样推出自己的模拟,也可以使用模拟框架.

回应那些说你可以像在Django中那样创建一个普通用户......我建议这会破坏单元测试的重点.单元测试不应该触及数据库,但是通过创建用户,您已经更改了数据库,因此我们想要模拟一个.

  • 除非您使用数据库,否则它不再是单元测试.它可能仍然是一个完全有效的集成测试,但它不是一个单元测试. (4认同)
  • 正如 Daniel 所提到的,测试运行程序会为您创建然后销毁一个测试数据库,因此您无需担心。 (2认同)

Anu*_*yal 6

在这里阅读有关模拟对象的信息
http://en.wikipedia.org/wiki/Mock_object
http://www.mockobjects.com/

并使用此python lib来模拟用户
http://python-mock.sourceforge.net/

否则你可以自己编写一个简单的User类,以此为出发点

class MockUser(object):
    def __call__(self, *args, **kwargs):
        return self

    def __getattr__(Self, name):
        return self
Run Code Online (Sandbox Code Playgroud)

添加特定案例等


Dan*_*man 5

您不需要模拟用户,因为您可以在测试中创建一个用户-测试完成后数据库将销毁。

要模拟请求,请使用Simon Willison的此代码段