0

我正在尝试模拟一个multiprocessing.Event对象,以便调用在第一次迭代时event.is_set()返回 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类。

4

2 回答 2

1

这是一种方法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(...)那仍然是有用的。

于 2020-02-18T00:46:50.743 回答
1

为了响应@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仅在装饰器中修补类,并is_set()在测试主体中模拟响应。老实说,我不知道为什么我们不能直接打补丁multiprocessing.Event.is_set,因为那multiprocessing.Eventthreading.Event.

于 2020-04-20T23:09:29.257 回答