Monkeypatch 导入函数请求模块 [Pytest]

Monkeypatch imported functions requests module [Pytest]

我遇到了一个问题,我需要测试一个调用 requests 的函数。推荐的方法是使用 monkeypatch 来避免 request 调用,但是所有资源都显示了一种使用函数外的 requests 模块来实现的方法:

import requests


def test_get_credentials(uri, code):
#the actual function, but rewritten here instead of just being imported

    def mocked_get(uri, *args, **kwargs):
    # this is a request answer mock to avoid calling external servers during tests
        json = {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}
        mock = type("MockedReq", (), {})()
        mock.json = json
        obj = mock
        return obj

    monkeypatch.setattr(requests, "post", mocked_get)    

    credentials = requests.post(uri, data=code).json()
    assert credentials == {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}

但我想使用导入函数,但没有找到从导入函数中修补请求模块的方法。类似于:

import requests
from external_auth import get_credentials

def test_get_credentials(uri, code):
    def mocked_get(uri, *args, **kwargs):
            json = {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}
            mock = type("MockedReq", (), {})()
            mock.json = json
            obj = mock
            return obj

        monkeypatch.setattr(requests, "post", mocked_get)

    assert get_credentials(uri, code) == {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}

我发现修补导入函数的方法是通过 __globals__ 函数属性更改 get_credentials.__globals__["requests"] 而不仅仅是 get_credentials。最终代码如下所示:

import requests
from external_auth import get_credentials

def test_get_credentials(uri, code):
    def mocked_get(uri, *args, **kwargs):
        json = {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}
        mock = type("MockedReq", (), {})()
        mock.json = json
        obj = mock
        return obj

    monkeypatch.setattr(get_credentials.__globals__["requests"], "post", mocked_get)

    assert get_credentials(uri, code) == {"token_type": "JWT", "access_token": "ioaUSHDAHwe9238hidnfiqh2wr89o"}