Как смоделировать multiprocessing.Event.is_set () - AttributeError - PullRequest
0 голосов
/ 18 февраля 2020

Я пытаюсь смоделировать объект 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 класс.

Ответы [ 2 ]

1 голос
/ 21 апреля 2020

Чтобы ответить на вызов @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.Event является клоном threading.Event.

1 голос
/ 18 февраля 2020

Вот способ сделать это с 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(...), это все равно будет полезно.

...