【问题标题】:How to test authenticated POST request with Pytest in Django如何在 Django 中使用 Pytest 测试经过身份验证的 POST 请求
【发布时间】:2019-12-01 07:38:21
【问题描述】:

我想使用 Pytest 在 API 上测试经过身份验证的发布请求。这就是我目前正在做的事情:

 def test_auth_user_can_create(self, client):
      
    
    url = api_reverse('crud-simulation_api')

    data = {
        "project": "testproject",
        ....
    }

        response = client.post(url, json=data)
        assert response.status_code == 200

这不起作用,因为它返回了 401(未经授权)而不是 200。这是有道理的,因为夹具是客户端而不是管理客户端。

但是,如果我传入 admin_client 而不是 client,它会给我一个错误的请求。不过我发送的数据应该没问题。

我也尝试像这样传递标头(因为我使用 JWT 授权):

token = "bigassstringwhichismytoken"

headers = {
        "Authorization": "JWT " + token
    }

最后我尝试登录之前,它给了我一个 403(禁止):

def test_auth_user_can_create_simulation_api(self, client, django_user_model):
     
    username = "Jack"
    password = "password"

    django_user_model.objects.create_user(username=username, password=password)
    client.login(username=username, password=password)

    url = api_reverse('crud-simulation_api')

    data = {
        "project": "testproject",
        ...
    }

    response = client.post(url, json=data)
    assert response.status_code == 200

如果有人能指出我正确的方向,那就太棒了!提前非常感谢

【问题讨论】:

    标签: python django django-rest-framework automated-tests pytest


    【解决方案1】:

    要为client.{request} 提供标头,将它们作为关键字参数单独传递:

    client.post(url, data, HTTP_FIRST_HEADER='...', HTTP_SECOND_HEADER='...')
    

    虽然您不太可能与post 调用链中的任何保留参数名称发生冲突,但最好在字典中收集您需要的所有标头:

    headers = {
        'HTTP_FIRST_HEADER': '...',
        'HTTP_SECOND_HEADER': '...',
    }
    

    并将它们作为任意数量的关键字参数传递给请求:

    client.post(url, data, **headers)
    

    在这种情况下,** 参数被视为extra information and are automatically added as headers

    【讨论】:

      【解决方案2】:

      您可以使用用户名和密码点击登录网址并获取令牌。 创建一个标题字典,如headers = {'Authorization': 'JWT <token>'}

      并在使用 post 时使用标题。

      client.post(url, json=data, headers=headers)
      

      【讨论】:

      • 感谢山姆的帮助!对不起,我可以用用户名和密码点击登录网址并获取令牌是什么意思?我继续并尝试使用auth_response = client.post(url_auth, username=username, password=password) 这是你的意思吗?我必须为此创建一个用户吗?
      • 不,您需要解析从client.login() 返回的令牌并将其用作client.post() 请求中的标头参数。
      • 再次感谢山姆。我按照这些步骤操作,但它仍然给我一个 400(错误请求)。我使用response = client.post(url_auth, data) token = response.data.get("token", 0) 获得了令牌然后我将令牌传递给标题,但仍然是 400。还有更多想法吗?
      • 没关系,我发送的数据有问题。
      • Authorization 不会作为标题传递,而是作为嵌套键在名为 headers 的新标题中传递。此解决方案不正确,不适用于默认的授权执行。
      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 2017-08-15
      • 2013-08-27
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      相关资源
      最近更新 更多