gpt4 book ai didi

python - Django Rest Framework 无法修补 View 测试中的 Serializer(many=True).data

转载 作者:行者123 更新时间:2023-12-01 09:02:55 25 4
gpt4 key购买 nike

我正在对 View 进行单元测试,并尝试修补序列化器上的 .data 属性,但当 many=True kwarg 时,它的行为似乎有所不同传递给序列化器构造函数,因此无法正确修补。这是我的代码的通用示例。

# myapp/serializers.py
class MySerializer(serializers.Serializer):
some_field = serializers.CharField()


# myapp/views.py
class MyView(View):

def get(self, request):
# ..stuff
some_data = []
serializer = MySerializer(some_data, many=True)
print(type(serializer)) # <class 'rest_framework.serializers.ListSerializer'>
print(type(serializer.data)) # <class 'rest_framework.utils.serializer_helpers.ReturnList'>


return Response({"data": seralizer.data, status=200})


# in tests
def test_view_case_one(mocker):

# setup other mocks

serialized_data = mocker.patch("myapp.views.MySerializer.data", new_callable=mocker.PropertyMock)

# invoke view
response = MyView().get(fake_request)

# run assertions
serialized_data.assert_called_once() # this says it's never called

最佳答案

早些时候,我在尝试修补rest_framework.serializers.ListSerializer.data时遇到了问题。一定是打字错误。重新尝试并能够成功修补。鉴于 many=True 将序列化器重新创建为 ListSerializer 的情况,我只需要修补底层类上的属性即可。

serialized_data = mocker.patch(
"rest_framework.serializers.ListSerializer.data",
new_callable=mocker.PropertyMock
)

编辑:更深入的答案

当使用many=True时,BaseSerializer上的__new__方法会抓取你的类并构造一个ListSerializer这就是为什么我的对象显示为 ListSerializer 的原因。由于我们实际上收到的是 ListSerializer 而不是我们定义的类,因此补丁不会应用于 ListSerializer.data 方法。 BaseSerializer 源代码的相关部分如下

class BaseSerializer(Field):

def __new__(cls, *args, **kwargs):
# We override this method in order to automagically create
# `ListSerializer` classes instead when `many=True` is set.
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)

@classmethod
def many_init(cls, *args, **kwargs):
"""
This method implements the creation of a `ListSerializer` parent
class when `many=True` is used. You can customize it if you need to
control which keyword arguments are passed to the parent, and
which are passed to the child.

Note that we're over-cautious in passing most arguments to both parent
and child classes in order to try to cover the general case. If you're
overriding this method you'll probably want something much simpler, eg:

@classmethod
def many_init(cls, *args, **kwargs):
kwargs['child'] = cls()
return CustomListSerializer(*args, **kwargs)
"""
allow_empty = kwargs.pop('allow_empty', None)
child_serializer = cls(*args, **kwargs)
list_kwargs = {
'child': child_serializer,
}
if allow_empty is not None:
list_kwargs['allow_empty'] = allow_empty
list_kwargs.update({
key: value for key, value in kwargs.items()
if key in LIST_SERIALIZER_KWARGS
})
meta = getattr(cls, 'Meta', None)
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
return list_serializer_class(*args, **list_kwargs)

关于python - Django Rest Framework 无法修补 View 测试中的 Serializer(many=True).data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52319519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com