“in”关键字覆盖模拟

时间:2018-01-29 17:24:24

标签: python mocking python-3.5 python-unittest

我正在嘲笑一个枚举,所以我可以独立于任何实际值来测试我的代码,但是如果我使用“in”关键字,那么我正在测试的函数中显然会覆盖mock。模拟在我正在测试的函数中可见,我真的不明白为什么会发生这种情况。

这是一个突出我问题的简短示例:

function.py:

from enum import Enum

class TestType(Enum):
    APPLE = 1

class CheckTheEnum():
    def get_enum_value(self, test_type):
        # "test" has a variable "TEST" here.
        test = TestType

        # this call always fails for the mock, but it works if I execute it for real.
        if test_type in TestType:
            return test_type.value
        else:
            raise NameError

test.py:

from unittest import TestCase, main
from unittest.mock import patch

from function import CheckTheEnum

class TestCheckTheEnum(TestCase):
    @patch('converter.test.TestType')
    def test_get_enum_value(self, mock_testtype):
        mock_testtype.TEST = 10

        checker = CheckTheEnum()
        value = checker.get_enum_value(mock_testtype.TEST)

        self.assertEqual(value, 10)

if __name__ == "__main__":
    main()

为什么不在这里找到mock_testtype.TEST?

1 个答案:

答案 0 :(得分:0)

请注意,在您模拟它之后,您的TestType对象不再是TestType,而是unittest.mock.MagicMock对象,因此您的in将会失败。

您可以在 TestType 枚举类中添加has_value方法:

class TestType(Enum):
    APPLE = 1

    @classmethod
    def has_value(cls, value):
        return any(value == item.value for item in cls)

然后将您的CheckTheEnum课程更改为:

class CheckTheEnum():
    def get_enum_value(self, test_type):
        # this call always fails for the mock, but it works if I execute it for real.
        value = TestType.has_value(test_type)
        if value:
            return value
        else:
            raise NameError

最后,不要嘲笑Enum模拟has_value方法:

from unittest import TestCase, main
from unittest.mock import patch

from function import CheckTheEnum

class TestCheckTheEnum(TestCase):
    @patch('converter.test.TestType.has_value', return_value=11)
    def test_get_enum_value(self, mock_testtype):

        checker = CheckTheEnum()
        value = checker.get_enum_value(mock_testtype.TEST)
        mock_testtype.assert_called_with(mock_testtype.TEST)

        self.assertEqual(value, 11)

if __name__ == "__main__":
    main()

只要改变它会返回什么。