如何模拟 multiprocessing.Event.is_set() - AttributeError
How to mock multiprocessing.Event.is_set() - AttributeError
我正在尝试模拟一个 multiprocessing.Event
对象,以便对 event.is_set()
returns 的调用在第一次迭代时为 False,在第二次迭代时为 true。我在以下尝试中失败了:
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch.object(multiprocessing.Event, 'is_set', return_value=False)
def test_my_method(self, mock_event):
mock_event.side_effect = [False, True]
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
我遇到了错误:
AttributeError: <bound method BaseContext.Event of <multiprocessing.context.DefaultContext object at 0x7f1068a50e48>> does not have the attribute 'is_set'
我无法覆盖 MyClassUnderTest.event
因为事件对象会立即使用,所以我试图覆盖整个 multiprocessing.Event
class.
这是一种使用 configure_mock
的方法:
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch('multiprocessing.Event')
def test_my_method(self, mock_event):
mock_event.configure_mock(**{'is_set.side_effect': [False, True]})
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
如果有人知道如何将其完全压缩成 @mock.patch(...)
,那仍然有用。
为了响应@David Parks 的号召,这里有一个简化的工作示例。
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch('multiprocessing.Event')
def test_my_method(self, mock_event):
mock_event.is_set.side_effect = [False, True]
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
诀窍是仅在装饰器中修补 Event
class,并在测试主体中模拟 is_set()
的响应。老实说,我不知道为什么我们不能直接修补 multiprocessing.Event.is_set
,因为 multiprocessing.Event
是 threading.Event
的克隆。
我正在尝试模拟一个 multiprocessing.Event
对象,以便对 event.is_set()
returns 的调用在第一次迭代时为 False,在第二次迭代时为 true。我在以下尝试中失败了:
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch.object(multiprocessing.Event, 'is_set', return_value=False)
def test_my_method(self, mock_event):
mock_event.side_effect = [False, True]
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
我遇到了错误:
AttributeError: <bound method BaseContext.Event of <multiprocessing.context.DefaultContext object at 0x7f1068a50e48>> does not have the attribute 'is_set'
我无法覆盖 MyClassUnderTest.event
因为事件对象会立即使用,所以我试图覆盖整个 multiprocessing.Event
class.
这是一种使用 configure_mock
的方法:
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch('multiprocessing.Event')
def test_my_method(self, mock_event):
mock_event.configure_mock(**{'is_set.side_effect': [False, True]})
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
如果有人知道如何将其完全压缩成 @mock.patch(...)
,那仍然有用。
为了响应@David Parks 的号召,这里有一个简化的工作示例。
import unittest
import unittest.mock as mock
import multiprocessing
class MyClassUnderTest:
def __init__(self):
self.event = multiprocessing.Event()
# start a Process which immediately uses self.event
def my_method_under_test(self):
while not self.event.is_set():
pass # do something
return True
class TestMyClassUnderTest(unittest.TestCase):
@mock.patch('multiprocessing.Event')
def test_my_method(self, mock_event):
mock_event.is_set.side_effect = [False, True]
myobj = MyClassUnderTest()
self.assertTrue(myobj.my_method_under_test())
诀窍是仅在装饰器中修补 Event
class,并在测试主体中模拟 is_set()
的响应。老实说,我不知道为什么我们不能直接修补 multiprocessing.Event.is_set
,因为 multiprocessing.Event
是 threading.Event
的克隆。