python - 修补 Django 中的多个 ORM 调用

标签 python django unit-testing orm

我的 Django 应用程序中有一个服务层,其中有一些业务逻辑和相应的数据检索代码。现在,当我编写单元测试时,我想模拟对 ORM 的调用,以便我仅测试服务层

我的服务层看起来像这样:

from .models import Event

class EventService():

    def get_client_separated_events(self):
        # Some complex business logic goes here
        qs = Event.objects.all()
        # Some complex business logic here as well
        return foo

当我测试 EventService 类时,我希望完全模拟 Events.objects.all() 等调用。截至目前,我正在使用 patch 来实现此目的:

class TestEventService(TestCase):

@classmethod
def setUpTestData(cls):
    cls.event_service = EventService()
    cls.dummy_events = [Event(id=1, name='n1', description='d1'), Event(id=2, name='n2', description='d2')]

@patch('foo.bar.Events.objects.all')
def test_get_all(self, get_events):
    get_events.return_value = self.dummy_events
    expected_events = self.event_service.get_all()
    self.assertListEqual(expected_Events, self.dummy_events, msg="Assertion failed for get_all method "
                                                                     "in Event Service")

但是,可能有十个这样的不同 ORM 调用,我不想编写十行的 @patch 语句来模拟它们。我在网上读到 @patch.multiple 可以做到这一点 - 但我不太知道这是否是正确的方法。有人可以帮忙吗?

最佳答案

虽然您可以直接模拟 ORM 并返回任意结果,但我认为使用诸如 factory_boy 之类的库在数据库中插入虚假数据会更有效。并使 ORM 调用保持未模拟状态:

class EventFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = 'myapp.Event'


class TestEventService(TestCase):

    @classmethod
    def setUpTestData(cls):
        cls.event_service = EventService()

    def test_get_all(self):
        expected = [EventFactory() for i in range(10)]
        self.assertListEqual(
            self.event_service.get_all(),
            expected)

在某些时候,您无法模拟所有内容,如果您模拟 ORM 调用,您最终可能会通过测试,而您的代码实际上有错误(例如,如果您的过滤器中有错误)或排除语句。

如果您可以轻松测试它,并保持测试快速高效,我认为您应该避免 mock 某些东西。对于您的情况:

  • 您可以轻松创建虚拟数据
  • 如果您使用 ORM,您的测试仍然会很快,因为 Django 默认情况下在测试期间使用内存中的 SQLite 数据库,从而避免了磁盘 I/O。

不过,模拟在其他情况下完全有意义,例如使用 HTTP API 通过网络检索数据。

关于python - 修补 Django 中的多个 ORM 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42251670/

相关文章:

python - 即使需要字段也会创建对象

java - 我是否需要测试接口(interface)的每个实现来测试接口(interface)?

c++ - 使用 gtest 1.6 : how to check what is printed out? 进行单元测试

python - 为什么我不能在 collections.MutableMapping 的子类上对 __setitem__ 进行猴子修补

python - Scrapy - TypeError : Cannot convert unicode body - HtmlResponse has no encoding

Django South迁移错误

node.js - Mocha异步测试,重用相同的请求

python - 3次握手并在python中使用scapy获取请求

python - 在另一个框架中调用函数 (WxPython)

django:为什么 RequestContext 设置为 context_instance?