問(wèn)題描述
我是 Python 中的新手.我想知道如何在用另一個(gè)類(lèi)方法進(jìn)行測(cè)試時(shí)替換(模擬)一個(gè)類(lèi)方法,知道原來(lái)的只是改變了 self 的一些屬性而不返回任何值.例如:
I am new to mock in Python. I want to know how to replace (mock) a class method while testing with another one, knowing that the original just changes some attributes of self without returning any value. For example:
def some_method(self):
self.x = 4
self.y = 6
所以在這里我不能只更改模擬的 return_value.我試圖定義一個(gè)新函數(shù)(應(yīng)該替換原來(lái)的函數(shù))并將其作為 side_effect 提供給模擬.但是我怎樣才能讓模擬函數(shù)改變類(lèi)中對(duì)象的屬性.這是我的代碼:
So here I can't just change the return_value of the mock. I tried to define a new function (that should replace the original) and give it as side_effect to the mock. But how can I make the mocking function change attributes of the object in the class. Here is my code:
@patch('path.myClass.some_method')
def test_this(self,someMethod):
def replacer(self):
self.x = 5
self.y = 16
some_method.side_effect = replacer
那么 Python 現(xiàn)在是如何理解替換器的 self
參數(shù)的呢?是測(cè)試類(lèi)的self,還是被測(cè)類(lèi)的對(duì)象self?
So how does Python now understands the self
argument of replacer? Is that the self of the test class, or the self as the object of the class under test?
推薦答案
如果我不明白您要做什么,請(qǐng)?zhí)崆暗狼福艺J(rèn)為這可能有效:
Apologies in advance if I don't understand what you are trying to do, but I think this might work:
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()
這在打補(bǔ)丁的時(shí)候用 other_method() 替換了 some_method(),它為屬性 x、y 設(shè)置了不同的值,并且在運(yùn)行測(cè)試時(shí),它給出了結(jié)果:
This replaces some_method() with other_method() when patched, which sets different values for attributes x, y, and when the test is run, it gives the results:
..
----------------------------------------------------------------------
Ran 2 tests in 0.020s
OK
回答有關(guān)如何在不模擬類(lèi)的情況下在測(cè)試函數(shù)中執(zhí)行的問(wèn)題...
to answer question about how to do inside the test function without mocking a class...
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()
確保在補(bǔ)丁程序上調(diào)用 start() 和 stop() ,否則您可能會(huì)遇到補(bǔ)丁處于活動(dòng)狀態(tài)而您不希望它處于活動(dòng)狀態(tài)的情況.請(qǐng)注意,在測(cè)試代碼函數(shù)中定義模擬函數(shù),我沒(méi)有使用補(bǔ)丁作為裝飾器,因?yàn)槟M函數(shù)必須在補(bǔ)丁中使用'new'關(guān)鍵字之前定義.如果你想使用補(bǔ)丁作為裝飾器,你必須在補(bǔ)丁之前的某個(gè)地方定義模擬函數(shù),在 MyTestClass 中定義它也可以,但似乎你真的希望在測(cè)試函數(shù)代碼中定義模擬函數(shù).
Make sure you call start() and stop() on the patcher otherwise you can get into a situation where the patch is active and you don't want it to be. Note that to define the mock function inside the test code function, I didn't use patch as a decorator, because the mock function has to be defined before using the 'new' keyword in patch. If you want to use patch as a decorator you have to define the mock function someplace before the patch, defining it inside of MyTestClass also works, but it seems you really want to have the mock function defined inside your test function code.
添加了我看到的 4 種方法的摘要...
added summary of 4 ways I see to do this...
# 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()
這些都沒(méi)有使用副作用,但它們都解決了模擬類(lèi)方法和更改某些屬性的問(wèn)題.您選擇哪一種取決于應(yīng)用程序.
None of these uses a side_effect, but they all solve the problem of mocking a class method and changing some attributes. Which one you choose depends on the application.
這篇關(guān)于在 Python 中模擬類(lèi)方法并更改某些對(duì)象屬性的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!