簡體   English   中英

為什么 python 模擬補丁不起作用?

[英]Why python mock patch doesn't work?

我有兩個文件

尖峰.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:

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()

當我運行python test_spike.py時,第一個測試用例會通過,但第二個會失敗。 然后我切換到使用nosetests test_spike.py ,然后兩個都失敗了。

我不明白這是怎么發生的? 這些案件應該全部通過。

使用spike.bar訪問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()

對於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)

這給了我:

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

OK

現在第二個示例不起作用,因為您導入 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()

這給了我:

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

OK

但是當我嘗試用鼻子運行它時,我得到:

 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)

發生這種情況是因為我修補的位置不正確。 我的目錄結構是:

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

我從 src 目錄運行測試,所以我應該使用來自項目根目錄的路徑進行修補,例如:

@patch('src.spike.bar')

這會給我:

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

OK

或者如果我在測試目錄:

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

OK

為了詳細說明非常有用的最佳答案,讓我解釋一下unittest.mock的官方文檔。

a.py
    class SomeClass:
        ...

b.py
    import a
    from a import SomeClass
    def some_function():
        a.SomeClass()
        SomeClass()

如果您編寫mock.patch('a.SomeClass') ,這將影響some_function的第一行。 如果您編寫mock.patch('b.SomeClass') ,這將影響第二行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM