简体   繁体   English

Python 模拟补丁不是 mocking object

[英]Python mock patch not mocking the object

I am using the python mocking library and I am not sure why I get this result.我正在使用 python mocking 库,但我不确定为什么会得到这个结果。 Why only the second one got mocked and not the first one?为什么只有第二个被嘲笑而不是第一个? What's the best way to do it?最好的方法是什么?

import unittest
from unittest.mock import patch, Mock

import requests
from requests import Session


def my_func():
    s = Session()
    print('my_func', type(s))


def my_func2():
    s = requests.Session()
    print('my_func2', type(s))


class Test(unittest.TestCase):

    @patch("requests.Session", new=Mock)
    def test1(self, *args):
        my_func()

    @patch("requests.Session", new=Mock)
    def test2(self, *args):
        my_func2()

Output Output

my_func <class 'requests.sessions.Session'>
my_func2 <class 'unittest.mock.Mock'>

This is a tricky nuance about Python namespaces.这是关于 Python 命名空间的一个微妙的细微差别。 In the first one, my_func() , you used just Session (after importing it into your module namespace with from requests import Session ).在第一个my_func()中,您只使用了Session (在使用from requests import Session将其导入您的模块命名空间之后)。 In my_func2() you used requests.Session .my_func2()你使用requests.Session

@patch('requests.Session') is replacing Session in the requests module, so requests.Session will be the mock object. @patch('requests.Session')正在替换requests模块Session ,因此requests.Session将是模拟 object。 But it does not replace every reference to Session in every module--in fact that would be very difficult to do in Python.但它并不能取代每个模块中对Session的所有引用——事实上,在 Python 中很难做到这一点。

Really, on a basic level, what patch() is doing is just setting requests.Session = Mock() .实际上,在基本层面上, patch()所做的只是设置requests.Session = Mock() But to replace the reference to Session that's already in your module's global namespace it would have to set globals()['Session'] = Mock() as well.但是要替换对Session的引用,它已经在你的模块的全局命名空间中,它还必须设置globals()['Session'] = Mock()

In other words, you have to patch the object in the correct namespace.换句话说,您必须在正确的命名空间中修补 object。

If you have some module foo.py that contains:如果你有一些模块foo.py包含:

from requests import Session

def my_func():
    s = Session()
    ...

then a separate test module test_foo.py in which you want to mock the Session class, you have to patch it in the namespace of foo , like:然后是一个单独的测试模块test_foo.py ,您要在其中模拟Session class,您必须在foo的命名空间中对其进行修补,例如:

import foo

@patch('foo.Session', ...)
def test_my_func():
    ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM