【问题标题】:How to pass context when testing deletion of an instance?测试删除实例时如何传递上下文?
【发布时间】:2019-09-12 03:00:50
【问题描述】:

我有几个模型,CarCertifyRequest。当Car 实例被创建、修改或删除时,我需要创建一个CertifyRequest,而这又需要手动批准。 CertifyRequest 实例包含它的创建时间。

我已经通过将context={"now": …} 注入CarSerializer 实例来测试创建和修改,但我不知道在删除时如何执行等效操作:

  1. 删除请求永远不会传递给序列化程序,因此我无法以相同的方式访问上下文。
  2. 我可以覆盖ModelViewSet 中的destroy 并在其中使用get_serializer_context,但是
    1. 我似乎无法将序列化程序传递给 ModelViewSet 实例和
    2. the implementation 无论如何都会返回一个完全不同的上下文。
  3. 我不想使用可选查询参数或测试时间“接近”当前测试客户端时间等可怕的技巧。

我目前使用的技巧是在Request 上设置一个额外的now 属性,并将其传递给视图,然后在destroy 中查找它。

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    如果您在视图中使用 Django 的 timezone.now() 来获取当前时间,则可以模拟该方法以在测试中返回特定时间并针对该时间进行断言。

    def test_destroy_car():
        client = APIClient()
        @mock.patch("application.views.timezone.now") as now:
            destroy_time = datetime.datetime(2019, 4, 23, 11, 2, 0)
            now.return_value = destroy_time
            response = client.destroy("/api/car/12345/")
            assert response.status_code == status.HTTP_204_NO_CONTENT, "The request to delete did not return a 204 response"
            certify_request = CertifyRequest.objects.order_by("id").last()
            assert certify_request.created_at == destroy_time, "CertifyRequest destroy time is incorrect"
    

    【讨论】:

    • 我正在寻找一种注入价值而不是模拟的方法。模拟依赖于“了解”实现的测试,如本例所示,您需要知道要模拟哪个特定函数,因此它会导致更脆弱的测试。
    • 我不认为使用特定代码修改视图/序列化程序以支持您的测试(请求中的自定义属性)要好得多。在我看来,您的测试需要知道它需要模拟哪个特定的请求属性,以便视图注入值。关于使用日期/时间对象进行测试的类似问题使用模拟:stackoverflow.com/questions/1042900/…
    • 当然,这就是为什么我认为我当前的解决方案是一个 hack,这也是询问的主要原因。但是在使用模拟和注入之后,我更喜欢后者。
    猜你喜欢
    • 2017-08-30
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多