使用自定义创建动作测试DRF模型时出现KeyError

时间:2020-04-08 10:09:59

标签: python testing django-rest-framework

将自定义create方法添加到模型后,许多测试开始失败。当仅执行“阶段1”时一切都很好,但是添加了“阶段2”后:通过GL的API创建GitLab项目,很多测试失败了。

模型是这样定义的:

class CarModelViewSet(viewsets.ModelViewSet):
   queryset = CarModel.objects.all()
   serializer_class = CarModelSerializer
   lookup_field = 'model_id'

   def create(self, request, *args, **kwargs):
      ## stage 1:
      serializer = self.get_serializer(data=request.data)
      serializer.is_valid(raise_exception=True)
      serializer.save()

      ## stage 2:
      proj_name = str(serializer.data['model_id']) + str(serializer.data['name']).replace(' ', '_')
      proj_desc = str(serializer.data['name']) + ' Project'

      req_headers = {
                     'content-type': 'application/json',
                     'PRIVATE-TOKEN': settings.REPOSITORY_TOKEN
      }
      req_body = {
                  "name": proj_name,
                  "namespace_id": 10,
                  "description": proj_desc
      }

      repository_url = 'https://gitlab.example.com/api/v4/projects/'
      res = requests.post(repository_url, json.dumps(req_body), headers=req_headers)
      response = res.json()
      response_msg = {
         "message": "Model added to database. Project created in GitLab.",
         "id": response["id"], ########### KeyError: 'id'
         "name": response["name"],
         "name_with_namespace": response["name_with_namespace"],
         "ssh_url_to_repo": response["ssh_url_to_repo"],
         "http_url_to_repo": response["http_url_to_repo"],
         "web_url": response["web_url"]
      }

      return Response(response_msg, status=status.HTTP_201_CREATED)

示例测试:

class CarModelTests(TestCase):

    def setUp(self):
        self.client = APIClient()

    def test_create_correct_car_model(self):
        """Test creating valid Car Model instance."""
        payload = {
            "model_id": "12/34/5678-9",
            "name": "Test Model",
            "active": True
            }

        res = self.client.post(CAR_MODELS_URL, payload)

        models = CarModel.objects.all()
        serializer = CarModelSerializer(models, many=True)

        self.assertEqual(res.status_code, status.HTTP_201_CREATED)
        print(json.dumps(serializer.data))
        self.assertEqual("Model added to database. Project created in GitLab.",
                            json.dumps(serializer.data[0]["message"]))

测试报告指出带有"id": response["id"]的那一行是失败的(不确定测试运行是否在这一点上终止并且没有报告其他运行,或者仅仅是此条目失败了。)

手动测试工作正常,模型已在数据库中创建,新项目出现在GitLab中。

我应该怎么做才能克服这种失败?

2 个答案:

答案 0 :(得分:1)

添加了“第2阶段”:通过GL的API创建GitLab项目后,许多测试失败了。

测试已经创建了一个项目和项目ID;任何进一步的测试都将失败,因为该项目已经存在。 要检查它是否存在,请执行GET /users/:user_id/projects或任何类似的请求,并检查要在响应中创建的项目的名称(或其他名称)。
看起来像这样:

[
  {
    "id": 4,
    "description": null,
    "default_branch": "master",
    "visibility": "private",
    "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
    "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
    "web_url": "http://example.com/diaspora/diaspora-client",
    "readme_url": "http://example.com/diaspora/diaspora-client/blob/master/README.md",
    "tag_list": [
      "example",
      "disapora client"
    ],
    "owner": {
      "id": 3,
      "name": "Diaspora",
      "created_at": "2013-09-30T13:46:02Z"
    },
    "name": "Diaspora Client",
    "name_with_namespace": "Diaspora / Diaspora Client",
    "path": "diaspora-client",
    "path_with_namespace": "diaspora/diaspora-client",
    "issues_enabled": true,
    "open_issues_count": 1,
    "merge_requests_enabled": true,
    "jobs_enabled": true,
    "wiki_enabled": true,
    "snippets_enabled": false,
    "can_create_merge_request_in": true,
    "resolve_outdated_diff_discussions": false,
    "container_registry_enabled": false,
    "created_at": "2013-09-30T13:46:02Z",
    "last_activity_at": "2013-09-30T13:46:02Z",
    "creator_id": 3,
    "namespace": {
      "id": 3,
      "name": "Diaspora",
      "path": "diaspora",
      "kind": "group",
      "full_path": "diaspora"
    },
    "import_status": "none",
    "archived": false,
    "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png",
    "shared_runners_enabled": true,
    "forks_count": 0,
    "star_count": 0,
    "runners_token": "b8547b1dc37721d05889db52fa2f02",
    "ci_default_git_depth": 50,
    "public_jobs": true,
    "shared_with_groups": [],
    "only_allow_merge_if_pipeline_succeeds": false,
    "only_allow_merge_if_all_discussions_are_resolved": false,
    "remove_source_branch_after_merge": false,
    "request_access_enabled": false,
    "merge_method": "merge",
    "autoclose_referenced_issues": true,
    "suggestion_commit_message": null,
    "marked_for_deletion_at": "2020-04-03", // to be deprecated in GitLab 13.0 in favor of marked_for_deletion_on
    "marked_for_deletion_on": "2020-04-03",
    "statistics": {
      "commit_count": 37,
      "storage_size": 1038090,
      "repository_size": 1038090,
      "wiki_size" : 0,
      "lfs_objects_size": 0,
      "job_artifacts_size": 0,
      "packages_size": 0
    },
    "_links": {
      "self": "http://example.com/api/v4/projects",
      "issues": "http://example.com/api/v4/projects/1/issues",
      "merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
      "repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
      "labels": "http://example.com/api/v4/projects/1/labels",
      "events": "http://example.com/api/v4/projects/1/events",
      "members": "http://example.com/api/v4/projects/1/members"
    }
  },
  {
    "id": 6,
    "description": null,
    "default_branch": "master",
    "visibility": "private",
    "ssh_url_to_repo": "git@example.com:brightbox/puppet.git",
    "http_url_to_repo": "http://example.com/brightbox/puppet.git",
    "web_url": "http://example.com/brightbox/puppet",
    "readme_url": "http://example.com/brightbox/puppet/blob/master/README.md",
    "tag_list": [
      "example",
      "puppet"
    ],
    "owner": {
      "id": 4,
      "name": "Brightbox",
      "created_at": "2013-09-30T13:46:02Z"
    },
    "name": "Puppet",
    "name_with_namespace": "Brightbox / Puppet",
    "path": "puppet",
    "path_with_namespace": "brightbox/puppet",
    "issues_enabled": true,
    "open_issues_count": 1,
    "merge_requests_enabled": true,
    "jobs_enabled": true,
    "wiki_enabled": true,
    "snippets_enabled": false,
    "can_create_merge_request_in": true,
    "resolve_outdated_diff_discussions": false,
    "container_registry_enabled": false,
    "created_at": "2013-09-30T13:46:02Z",
    "last_activity_at": "2013-09-30T13:46:02Z",
    "creator_id": 3,
    "namespace": {
      "id": 4,
      "name": "Brightbox",
      "path": "brightbox",
      "kind": "group",
      "full_path": "brightbox"
    },
    "import_status": "none",
    "import_error": null,
    "permissions": {
      "project_access": {
        "access_level": 10,
        "notification_level": 3
      },
      "group_access": {
        "access_level": 50,
        "notification_level": 3
      }
    },
    "archived": false,
    "avatar_url": null,
    "shared_runners_enabled": true,
    "forks_count": 0,
    "star_count": 0,
    "runners_token": "b8547b1dc37721d05889db52fa2f02",
    "ci_default_git_depth": 0,
    "public_jobs": true,
    "shared_with_groups": [],
    "only_allow_merge_if_pipeline_succeeds": false,
    "only_allow_merge_if_all_discussions_are_resolved": false,
    "remove_source_branch_after_merge": false,
    "request_access_enabled": false,
    "merge_method": "merge",
    "auto_devops_enabled": true,
    "auto_devops_deploy_strategy": "continuous",
    "repository_storage": "default",
    "approvals_before_merge": 0,
    "mirror": false,
    "mirror_user_id": 45,
    "mirror_trigger_builds": false,
    "only_mirror_protected_branches": false,
    "mirror_overwrites_diverged_branches": false,
    "external_authorization_classification_label": null,
    "packages_enabled": true,
    "service_desk_enabled": false,
    "service_desk_address": null,
    "autoclose_referenced_issues": true,
    "suggestion_commit_message": null,
    "statistics": {
      "commit_count": 12,
      "storage_size": 2066080,
      "repository_size": 2066080,
      "wiki_size" : 0,
      "lfs_objects_size": 0,
      "job_artifacts_size": 0,
      "packages_size": 0
    },
    "_links": {
      "self": "http://example.com/api/v4/projects",
      "issues": "http://example.com/api/v4/projects/1/issues",
      "merge_requests": "http://example.com/api/v4/projects/1/merge_requests",
      "repo_branches": "http://example.com/api/v4/projects/1/repository_branches",
      "labels": "http://example.com/api/v4/projects/1/labels",
      "events": "http://example.com/api/v4/projects/1/events",
      "members": "http://example.com/api/v4/projects/1/members"
    }
  }
]

我还建议您使用python-gitlab。它具有许多使这些事情变得容易的功能。

答案 1 :(得分:0)

您的问题在于以下行:

res = requests.post(repository_url, json.dumps(req_body), headers=req_headers)

将其更改为:

res = requests.post(repository_url, json=req_body, headers=req_headers)

请注意,您不必编码请求JSON数据