如何模拟自定义节流类以在 django-rest-framework 中进行测试?

Mas*_*Man 5 python testing django unit-testing django-rest-framework

我有一个自定义节流阀类,例如:(打印语句用于调试:)api.throttle.py

print("befor CustomThrottle class")
class CustomThrottle(BaseThrottle):
    def __init__(self):
        super().__init__()
        print("initializing CustomThrottle", self)
        self._wait = 0

    def allow_request(self, request, view):
        print("CustomThrottle.allow_request")
        if request.method in SAFE_METHODS:
            return True
        # some checking here
        if wait > 0:
            self._wait = wait
            return False
        return True

    def wait(self):
        return self._wait
Run Code Online (Sandbox Code Playgroud)

我的api.views.py就像:

from api.throttle import CustomThrottle

print("views module")
class SomeView(APIView):
    print("in view")
    throttle_classes = [CustomThrottle]

    def post(self, request, should_exist):
        # some processing
        return Response({"message": "Done."})
Run Code Online (Sandbox Code Playgroud)

我的测试是api/tests/test_views.py

    @patch.object(api.views.CustomThrottle, "allow_request")
    def test_can_get_confirmation_code_for_registered_user(self, throttle):
        throttle.return_value = True
        response = self.client.post(path, data=data)
        self.assertEqual(
            response.status_code,
            status.HTTP_200_OK,
            "Should be successful",
        )

    @patch("api.views.CustomThrottle")
    def test_learn(self, throttle):
        throttle.return_value.allow_request.return_value = True
        response = self.client.post(path, data=data)
        self.assertEqual(
            response.status_code,
            status.HTTP_200_OK,
            "Should be successful",
        )
Run Code Online (Sandbox Code Playgroud)


第一个测试正确通过,但CustomThrottle类仍然被实例化,但allow_request方法被模拟;第二个测试表明,CustomThrottle类和allow_request方法都没有被模拟,并且失败status 429CustomThrottle节流率为 2 分钟)。

Mas*_*Man 2

在花了一些时间并测试不同的场景(在此处和那里放置像打印语句这样的调试:))之后,我终于找到了它不起作用的原因,但它可能不像我想象的那么正确,所以欢迎任何更好的答案

我定义了节流类列表,就像这样,当服务器启动时,它会被导入并评估,因此在我的类中throttle_classes = [CustomThrottle]存在对实际和未模拟版本的引用,并且在处理响应时,它将使用它进行实例化,因此我的测试失败,但是当我修补时就像当视图实际上需要检查节流阀时,它会调用类似的东西(注意对象创建的括号);该对象没有像其本身那样的方法,因此它会在其类中搜索该方法并正确使用模拟版本。CustomThrottleSomeViewpatch.object(CustomThrottle, "allow_request")CustomThrottle().allow_request(...)allow_request