模拟修补类方法不起作用

Dan*_*tas 5 python django django-unittest python-mock django-rest-framework

我将 Django 与 DRF 和 python 模拟一起使用。我想做的是测试我的视图并模拟序列化器和一些方法。

这就是我所拥有的:

views.py

from gmm_mobile.v1.serializers import RegisterParticipationSerializer
from gmm_mobile.v1.exceptions import GameOrCampaignDoesNotExist
from gmm_util.header import Header
from gmm_util.response import ResponseUtils
from gmm_util.permissions import MobileTokenPermission
from gmm_util.permissions import MobileTokenAuthentication

class ParticipantViewMobile(APIView):
    permission_classes = (MobileTokenPermission, )
    authentication_classes = (MobileTokenAuthentication, )

    def post(self, request, service_id, campaign_id):
        try:
            environment_info = Header.get_environment_info(request)

            request.data[Field.GAME_SERVICE_ID] = service_id
            request.data[Field.CAMPAIGN] = campaign_id
            request.data[Field.LOCATION] = environment_info

            participation_serializer = RegisterParticipationSerializer(data=request.data)
            participation_serializer.is_valid(raise_exception=True)
            participation_serializer.save()

            return ResponseUtils.created()
        except Http404:
            raise GameOrCampaignDoesNotExist()
Run Code Online (Sandbox Code Playgroud)

serializers.py

from gmm_mobile.v1.serializers import RegisterParticipationSerializer
from gmm_mobile.v1.exceptions import GameOrCampaignDoesNotExist
from gmm_util.header import Header
from gmm_util.response import ResponseUtils
from gmm_util.permissions import MobileTokenPermission
from gmm_util.permissions import MobileTokenAuthentication

class ParticipantViewMobile(APIView):
    permission_classes = (MobileTokenPermission, )
    authentication_classes = (MobileTokenAuthentication, )

    def post(self, request, service_id, campaign_id):
        try:
            environment_info = Header.get_environment_info(request)

            request.data[Field.GAME_SERVICE_ID] = service_id
            request.data[Field.CAMPAIGN] = campaign_id
            request.data[Field.LOCATION] = environment_info

            participation_serializer = RegisterParticipationSerializer(data=request.data)
            participation_serializer.is_valid(raise_exception=True)
            participation_serializer.save()

            return ResponseUtils.created()
        except Http404:
            raise GameOrCampaignDoesNotExist()
Run Code Online (Sandbox Code Playgroud)

test_views.py

class RegisterParticipationSerializer(serializers.ModelSerializer):
    location = LocationSerializer(many=False)
    campaign = serializers.IntegerField()
    game_service_id = serializers.CharField(max_length=254)

    class Meta:
        model = Participation
        fields = (Field.PK, Field.EMAIL, Field.GPG_ID, Field.DATE, Field.LOCATION, Field.INFO, Field.CAMPAIGN,
                  Field.GAME_SERVICE_ID, Field.GCM_ID)
        read_only_fields = (Field.GCM_ID,)
Run Code Online (Sandbox Code Playgroud)

但是当我运行测试时,副作用不起作用。当我在测试中更改 时,.is_valid它对 没有影响ParticipantViewMobile.post

如果我这样做@patch('gmm_mobile.v1.views.RegisterParticipationSerializer.is_valid')并且mock_serializer.side_effect = ValidationError({})它有效,但我不希望这样,因为在某些情况下我需要模拟多个方法,例如.save.is_valid

我也尝试过更改导入样式views.pytest_views.py但仍然不起作用。

我做错了什么或者遗漏了什么吗?

编辑1:

我在视图上打印了一些内容,试图了解发生了什么:

def post(self, request, service_id, campaign_id):
    try:
        environment_info = Header.get_environment_info(request)

        request.data[Field.GAME_SERVICE_ID] = service_id
        request.data[Field.CAMPAIGN] = campaign_id
        request.data[Field.LOCATION] = environment_info

        participation_serializer = RegisterParticipationSerializer(data=request.data)
        print RegisterParticipationSerializer.is_valid.side_effect
        print participation_serializer.is_valid.side_effect
        participation_serializer.is_valid(raise_exception=True)
        participation_serializer.save()

        return ResponseUtils.created()
    except Http404:
        raise GameOrCampaignDoesNotExist()
Run Code Online (Sandbox Code Playgroud)

和输出:

{}
None
Run Code Online (Sandbox Code Playgroud)

因此,当我创建 的实例时RegisterParticipationSerializer,我丢失了模拟方法。如何避免这种情况?

Der*_*wok 3

您的模拟不起作用,因为您正在模拟该类,而不是从该类生成的实例。尝试这个:

mock_instance = Mock()
mock_instance.is_valid.side_effect = ValidationError({})
mock_serializer.return_value = mock_instance
Run Code Online (Sandbox Code Playgroud)