Django / Python unittest side_effect用法

时间:2013-12-09 12:35:56

标签: python django python-unittest

可能成为“单元测试奇怪代码”系列的第二部分。我正在测试以下功能:

def filter_queryset(self):
    """
        Filter our base queryset
    """
    # Get our base queryset
    queryset = self.get_queryset()
    if self.tags:
        try:
            # Try the django-taggit way of filtering by tags
            queryset = queryset.filter(tags__name__in=self.tags)
        except FieldError:
            # Our queryset object is using django-taggable instead
            # filter by tags the ugly way...
            for tag in self.tags:
                queryset = queryset.filter(tags__icontains=tag)
    return queryset

首先让我向你保证,我意识到这......丑陋。现在我们正在使用两个不同的django标签库,django-taggit和django-taggable,这是一个悲哀的要求。 (切勿使用django-taggable)。这是一种通用的方式,我可以想到有一个过滤器功能,可以与最小量的大惊小怪。测试时发生的问题是,为了测试功能,我需要获取queryset.filter()来引发FieldError()。很好,很容易将其设置为具有副作用的模拟对象:

  def side_effect(*args, **kwargs):
        if kwargs.get("tags__name__in", None):
            return FieldError()

    mock_queryset = MagicMock()
    mock_queryset.filter.side_effect = side_effect

这个问题是因为引发了FieldError,所以filter()不能再用在函数的except部分,这意味着我无法测试正确的called_count或assert_any_call()等

除了代码库的动荡只使用一个版本的标记之外,有什么方法呢?

1 个答案:

答案 0 :(得分:1)

只需创建一个单独的函数,如果它被单向调用,则会引发FieldError,而在另一个函数中则不会:

expected_return = MagicMock()

def fake_filter(**kwargs):
    if 'tags__name__in' in kwargs:
        raise FieldError()
    if 'tags__icontains' in kwargs:
        return expected_return
    raise ValueError("Neither expected kwarg present")

mock_queryset = MagicMock()
mock_queryset.filter = fake_filter

等等。我现在看到你已经用你的副作用功能做到了,你可以做同样的事情但更多。