如何使用嘲笑覆盖Django视图进行测试?

时间:2019-06-19 19:01:50

标签: python django python-3.x mocking

是否可以通过模拟覆盖类中的函数行为?

这是针对python 3.6.8,django 2.2.2

views.py:


YEAR_PATTERN = r"\(\d{4}\)\s*$"
LOCKED_FROM_EXTERNAL_API = False


class FetchFromExternalApi(APIView):

    @staticmethod
    def fetch_from_url(source):
        return urlopen('http://files.grouplens.org/datasets/movielens/%s.zip' % source, timeout=1)

    def post(self, request):
        global LOCKED_FROM_EXTERNAL_API, YEAR_PATTERN
        if LOCKED_FROM_EXTERNAL_API is False:
            LOCKED_FROM_EXTERNAL_API = True
            try:
                source = request.data['source']
            except KeyError:
                LOCKED_FROM_EXTERNAL_API = False
                return Response('no source data in body',
                                status=status.HTTP_400_BAD_REQUEST)
            if source in settings.AVAILABLE_SOURCES:
                try:
                    response = self.fetch_from_url(request.data['source'])
                except URLError:
                    LOCKED_FROM_EXTERNAL_API = False
                    return Response("External server respond time out",
                                    status=status.HTTP_504_GATEWAY_TIMEOUT)

我想编写一个测试来替代fetch_from_url方法的行为,并对其进行完全模拟。

1 个答案:

答案 0 :(得分:1)

是的,您可以修补类的属性和方法。

在这种情况下,您还需要返回一个伪造的http响应对象,其中包含来自修补对象的预期数据。

示例:

class FakeResponse:
    """A class for creating fake http responses for the patched method"""
    def __init__(self, body, status):
        self.body = body
        self.status = status



class MyTest(TestCase):
    def test_something(self):
        with mock.patch('file_name.FetchFromExternalApi.fetch_from_url') as mock_fetch:
            # now the `mock_fetch` will act as a proxy object for the 
            # actual fetch_from_url method

            # set the return value on `mock_fetch` object as expected 
            # from the `fetch_from_url` method

            fake_response = FakeResponse(body="Some expected data body", status=200)

            mock_fetch.return_value = fake_response

            # now you can perform tests against the returned data
            self.assertTrue(whatever)