道歉提前如果我不明白你正在嘗試做的,但我認爲這可能工作:
import unittest
from unittest.mock import patch
class MyClass:
def __init__(self):
self.x = 0
self.y = 0
def some_method(self):
self.x = 4
self.y = 6
class OtherClass:
def other_method(self):
self.x = 5
self.y = 16
class MyTestClass(unittest.TestCase):
@patch('__main__.MyClass.some_method', new=OtherClass.other_method)
def test_patched(self):
a = MyClass()
a.some_method()
self.assertEqual(a.x, 5)
self.assertEqual(a.y, 16)
def test_not_patched(self):
a = MyClass()
a.some_method()
self.assertEqual(a.x, 4)
self.assertEqual(a.y, 6)
if __name__ == "__main__":
unittest.main()
這將替換some_method()與修補時,它設置不同的值other_method()爲屬性X,Y,並在測試運行時,它給出的結果:
..
----------------------------------------------------------------------
Ran 2 tests in 0.020s
OK
編輯:回答有關如何測試函數內部沒有做嘲笑的一類問題...
def test_inside_patch(self):
def othermethod(self):
self.x = 5
self.y = 16
patcher = patch('__main__.MyClass.some_method', new=othermethod)
patcher.start()
a = MyClass()
a.some_method()
self.assertEqual(a.x, 5)
self.assertEqual(a.y, 16)
patcher.stop()
確保您在修補程序上調用start()和stop(),否則您可能會遇到修補程序處於活動狀態而您不希望它發生的情況。請注意,爲了在測試代碼函數中定義模擬函數,我沒有使用補丁作爲裝飾器,因爲在補丁中使用'new'關鍵字之前必須定義模擬函數。如果你想使用補丁作爲裝飾器,你必須在補丁前定義模擬函數,在MyTestClass中定義它也可以,但似乎你真的想在你的測試函數代碼中定義模擬函數。
編輯:4點的方法,我看這樣做補充總結......這些
# first way uses a class outside MyTest class
class OtherClass:
def other_method(self):
...
class MyTest(unittest.TestCase):
@patch('path_to_MyClass.some_method', new=OtherClass.other_method)
def test_1(self)
...
# 2nd way uses class defined inside test class
class MyOtherClass:
def other_method(self):
...
@patch('path_to_MyClass.some_method', new=MyOtherClass.other_method)
def test_2(self):
...
# 3rd way uses function defined inside test class but before patch decorator
def another_method(self):
...
@patch('path_to_MyClass.some_method', new=another_method)
def test_3(self):
...
# 4th way uses function defined inside test function but without a decorator
def test_4(self):
def yet_another_method(self):
...
patcher = patch('path_to_MyClass.some_method', new=yet_another_method)
patcher.start()
...
patcher.stop()
無使用side_effect,但他們都解決嘲諷一個類的方法,改變一些屬性的問題。您選擇哪一個取決於應用程序。
謝謝你的回答。這非常有幫助。但是,在這個新班級中創造一個新班級,然後是一種新方法是否有必要?難道我只是在測試代碼中定義other_method,然後將其作爲side_effect賦予它? –
@AhmedAyadi是的,可以在測試函數代碼中定義模擬函數,但我不確定使用side_effect。看我的編輯到我的文章。 PS。如果這個答案解決了你的問題,請接受它,謝謝! –
非常感謝:)這確實回答了我的問題 –