简体   繁体   中英

Django / Python unittest side_effect usage

The second in what might become a series in "unittesting strange code". I have the following function I am testing:

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

First off let me assure you I realise that this is... ugly. It's a sad requirement for now that we are using two different django tag libraries, django-taggit and django-taggable. (Never use django-taggable). And this is about as generic a way as I can think of to have a filter function that works with both with the minimum amount of fuss. The issue that occurs when testing is that in order to test the functionality, I need to get queryset.filter() to raise a FieldError(). Fine, easily done with setting it up as a mock object with a side effect:

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

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

The issue with this is that because of the FieldError being raised, filter() can no longer be used in the except part of the function, meaning I cannot test for the correct called_count, or assert_any_call() etc.

Other than an upheaval of the codebase to only use one version of tagging, what are the ways around this?

Just make a separate function that raises FieldError if it's called one way, and doesn't in the other:

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

et cetera. I see now that you already do that with your side effect function, you can just do the same but more.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM