为什么python模拟补丁不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20242862/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:59:16  来源:igfitidea点击:

Why python mock patch doesn't work?

pythonunit-testingmockingnose

提问by LeoShi

I have two files

我有两个文件

spike.py

尖峰.py

class T1(object):
    def foo(self, afd):
        return "foo"

    def get_foo(self):
        return self.foo(1)


def bar():
    return "bar"

test_spike.py:

test_spike.py:

from unittest import TestCase
import unittest
from mock import patch, MagicMock
from spike import T1, bar


class TestStuff(TestCase):
    @patch('spike.T1.foo', MagicMock(return_value='patched'))
    def test_foo(self):
        foo = T1().get_foo()
        self.assertEqual('patched', foo)

    @patch('spike.bar')
    def test_bar(self, mock_obj):
        mock_obj.return_value = 'patched'
        bar = bar()
        self.assertEqual('patched', bar)


if __name__ == "__main__":
    unittest.main()

When I run python test_spike.py, the first test case would pass, but the second would fail. and I switch to use nosetests test_spike.py, then both two are failed.

当我运行时python test_spike.py,第一个测试用例会通过,但第二个会失败。我切换到使用nosetests test_spike.py,然后两个都失败了。

I don't understand how this happened? These cases supposed to pass all.

我不明白这是怎么发生的?这些情况应该全部通过。

采纳答案by ?ilvinas Rud?ionis

For test_fooyou are not using patch correctly. You should be using it like this:

对于test_foo您没有正确使用补丁。你应该像这样使用它:

class TestFoo(TestCase):
@patch.object(T1, 'foo', MagicMock(return_value='patched'))
def test_foo(self):
    foo = T1().get_foo()
    self.assertEqual('patched', foo)

that gives me:

这给了我:

nosetests test_spike.py 
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

Now the second example does not work because you import bar function (get a reference to it) and then try to mock it. When you mock something you can't change what your variables hold (reference to original function). To fix this you should use @falsetru suggested method like:

现在第二个示例不起作用,因为您导入 bar 函数(获取对它的引用)然后尝试模拟它。当您模拟某些内容时,您无法更改变量保存的内容(对原始函数的引用)。要解决此问题,您应该使用@falsetru 建议的方法,例如:

from unittest import TestCase
import unittest
from mock import patch
import spike


class TestFoo(TestCase):
    @patch('spike.bar')
    def test_bar(self, mock_obj):
        mock_obj.return_value = 'patched'
        value = spike.bar()
        self.assertEqual('patched', value)


if __name__ == "__main__":
    unittest.main()

this gives me:

这给了我:

python test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

But when I try to run it with nose I get:

但是当我尝试用鼻子运行它时,我得到:

 nosetests test_spike.py
F
======================================================================
FAIL: test_bar (src.test_spike.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/zilva/envs/test/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "/home/zilva/git/test/src/test_spike.py", line 11, in test_bar
    self.assertEqual('patched', value)
AssertionError: 'patched' != 'bar'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

This happends because I am patching not in the right place. My directory structure is:

发生这种情况是因为我修补的位置不正确。我的目录结构是:

test/
└── src/
    ├── spike.py
    ├── test_spike.py
    └── __init__.py

and I run tests from src directory so I should be patching using path from project root directory like:

我从 src 目录运行测试,所以我应该使用来自项目根目录的路径进行修补,例如:

@patch('src.spike.bar')

and this would give me:

这会给我:

nosetests test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

or if I am at test directory:

或者如果我在测试目录:

nosetests src/test_spike.py
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

回答by falsetru

Access barusing spike.bar. Imported baris not affected by mock.patch.

访问bar使用spike.bar。进口bar不受mock.patch.

from unittest import TestCase
import unittest
from mock import patch, MagicMock
from spike import T1
import spike # <----


class TestShit(TestCase):
    @patch('spike.T1.foo', MagicMock(return_value='patched'))
    def test_foo(self):
        foo = T1().get_foo()
        self.assertEqual('patched', foo)

    @patch('spike.bar')
    def test_bar(self, mock_obj):
        mock_obj.return_value = 'patched'
        bar = spike.bar() # <-----
        self.assertEqual('patched', bar)


if __name__ == "__main__":
    unittest.main()