【问题标题】:Django Testing - loading data into the database before loading the appsDjango 测试 - 在加载应用程序之前将数据加载到数据库中
【发布时间】:2017-07-04 15:59:24
【问题描述】:

我目前正在为 Django 应用程序(+ REST 框架)编写一些测试,并且在将测试数据加载到数据库中时遇到了一些问题。

让我用一些(非常简化的)代码来解释一下:

我有一个 django 视图,类似于:

view.py

from myapp.models import Item
from myapp.utils import MyClass

# need to initialize with the set of items
item_set = {item.name for item in Item.objects.all()}
my_class_object = MyClass(item_set)

class MyView(APIView):
    def post(selfself, request):
        result = my_class_object.process(request.data)
        return Response(result)

所以基本上我需要用数据库中的一些数据初始化一个类,然后在我的视图中使用这个类来处理端点接收到的数据。

现在测试:

my_test.py

from rest_framework.test import APILiveServerTestCase
from myapp.models import Item

class MyTest(APILiveServerTestCase):

    def setUp(self):
        self.URL = '/some_url_linking_to_myview/'

        # load some data
        Item.objects.create(name="first item")
        Item.objects.create(name="second item")

    def test_myview_return_correct_result(self):
        post_data = {"foo"}
        response = self.client.post(self.URL,
                                    data=post_data,
                                    format='json')
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data, {"my_expected_result"})

运行测试时,当前发生的是 view.pysetUp() 方法执行之前加载,所以当我用这两个实例化类时行:

item_set = {item.name for item in Item.objects.all()}
my_class_object = MyClass(item_set)

数据库仍然是空的。

我想知道是否有办法在执行 view.py 之前将数据导入数据库,或者在 setUp() 之后以某种方式强制重新加载应用程序,或者实例化我的类在其他地方加载数据后调用它?

谢谢!

【问题讨论】:

  • 这很好地说明了为什么您不应该将数据库访问代码放在模块级别。

标签: python django django-rest-framework django-testing django-tests


【解决方案1】:

我想你正在寻找setUpTestData()

如果我要使用大量数据,大致如下设置:

tests.py

from django.test import TestCase
from .tests.test_data import base_data

class MyClassTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        base_data.base_data(cls)

base_data.py

from .models import MyClass

def base_data(cls):
    cls.MyClass1 = MyClass.objects.create(
       name="first_name"
    )
    cls.MyClass2 = MyClass.objects.create(
       name="second_name"
    )

当然,您可以直接在 setUpTestData() 函数中执行所有操作,如果您希望测试数据位于顶部。

【讨论】:

  • 感谢亚当的回答。不幸的是,在这里使用 setUpTestData 并没有帮助(在实例化我的类后仍然填充数据库)。所以我的问题基本上是我在编译模块时访问数据库,这一切都发生在测试数据库设置之前!
【解决方案2】:

为什么不将启动代码放在函数中并从帖子内部调用。

class MyView(APIView):
    def initialize(self):
        item_set = {item.name for item in Item.objects.all()}
        my_class_object = MyClass(item_set)

    def post(self, request):
        self.initialize()
        result = my_class_object.process(request.data)
        return Response(result)

Edit 1 或者,您可以使用fixture 预先将MyClass 对象加载到数据库中

class MyTest(APILiveServerTestCase):
    fixtures = [
        // my class objects fixtures file
    ]
    def setUp():
        // rest of the code

【讨论】:

  • 这会起作用,但太慢了,因为它会为每个调用实例化类(查询所有项目并实例化类在这里是一项相当昂贵的操作,我真的只想做一次)。虽然我们可以将它与一些缓存策略结合起来..
  • 如果代码仅用于测试,那么您可以在 setUp 中对其进行实例化。但是,对于生产来说,全局实例化类并不是一个好习惯
  • 感谢您的输入,我尝试使用夹具但同样的问题:仅在实例化类后才会填充数据库。我可能会尝试使用布尔属性的第一种方法,以确保我们仅在第一次调用视图时实例化该类。但仍在寻找在 django 中处理这类事情的“正确”方式:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2017-02-03
  • 2013-07-31
  • 1970-01-01
相关资源
最近更新 更多