无法模拟继承自另一个类(该类创建/使用单例对象)的类

4

我有三个类和一个单元测试用例: 1)A.py:

class A(object):
    def __new__(cls):
        """
         Overriding the __new__ method to make the A a singleTon class
         :return: cls.instance
         """
        if not hasattr(cls, 'instance') or not cls.instance:
             cls.instance = super(A, cls).__new__(cls)
             return cls.instance
        def execute():
             print("class A")
             return "Coming from class A"

2)B.py:

from A import A
class B(object):
    def __init__(self):
        """
         Initialize and declare any members/methods that can be passed over class that inherit this class
        """
        self.a = A()
        self.name = Name()
    def run(self):
        pass

class Name:
    def __init__(self):
        self.test_dict = {}

3) C.py

from B import B
class C(B):
    def __init__(self):
        super(C, self).__init__()
        self.result = None

    def run(self):
        self.result = self.A.execute()
        return self.result

4) 测试.py

import unittest
from unittest.mock import patch
from A import A
from B import B
from C import C

class TestMethods(unittest.TestCase):

    @patch('A.A')
    def test_basic(self, MockA):
        a = MockA()
        a.execute.return_value = "Testing code"

        c = C()
        result = c.run()
        self.assertEqual(result,"Testing code")

if __name__ == '__main__':
    unittest.main()

执行test.py时,出现以下错误:

ERROR: test_basic (main.TestMethods)


该错误指示在执行test.py时发生了错误,并提供了相关信息。
Traceback (most recent call last):

File "C:\Users\davinder\AppData\Local\Continuum\Anaconda3\lib\unittest\mock.py", line 1179, in patched
   return func(*args, **keywargs)
File "C:/Users/davinder/PythonCodes/Test Framework/test.py", line 14, in test_basic
   c = C()
File "C:\Users\davinder\PythonCodes\Test Framework\C.py", line 5, in __init__
   super(C, self).__init__()
 File "C:\Users\davinder\PythonCodes\Test Framework\B.py", line 8, in __init__
    self.a = A()
 File "C:\Users\davinder\PythonCodes\Test Framework\A.py", line 8, in __new__
    cls.instance = super(A, cls).__new__(cls)
 TypeError: super() argument 1 must be type, not MagicMock

 ----------------------------------------------------------------------
 Ran 1 tests in 0.018s

 FAILED (errors=1)

我希望通过使用不同的返回值(通过打补丁)从test.py测试运行C.py类中的run()函数。 感谢您的帮助。
编辑:即使我在test.py中模拟了C类,如下所示:
import unittest
from unittest.mock import patch
from A import A
from B import B
from C import C
from B import Name

class TestMethods(unittest.TestCase):

    @patch('C.C')
    @patch('A.A')
    def test_basic(self, MockA, MockC):
        a1 = MockA()
        a1.execute.return_value = "Testing code"

        c = MockC()
        c.a = a1
        c.name = Name()

        result = c.run()
        self.assertEqual(result,"Testing code")

 if __name__ == '__main__':
     unittest.main()

出现以下错误:

FAIL: test_basic (__main__.TestMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
    File "C:\Users\davinder\AppData\Local\Continuum\Anaconda3\lib\unittest\mock.py", line 1179, in patched
        return func(*args, **keywargs)
    File "C:/Users/davinder/PythonCodes/Test Framework/test.py", line 22, in test_basic
        self.assertEqual(result,"Testing code")
 AssertionError: <MagicMock name='C().run()' id='2464384921272'> != 'Testing code'

 ----------------------------------------------------------------------
 Ran 1 tests in 0.018s

 FAILED (failures=1)
1个回答

4
我不得不在B.py中更改你的import,使其成为一个import而不是from。错误是因为AB模块中查找,所以你的补丁应该是@patch('B.A')。无论如何,这里有一个关于该主题的有用参考阅读:http://www.voidspace.org.uk/python/mock/patch.html#where-to-patch 现在,这里是修改后的代码:
"""test.py"""
import unittest
from unittest.mock import patch
from c_module import C

class TestMethods(unittest.TestCase):
    @patch('b_module.A')
    def test_basic(self, mock_a):
        mock_a.return_value.execute.return_value = "Testing code"
        c = C()
        result = c.run()
        self.assertEqual(result,"Testing code")

if __name__ == '__main__':
    unittest.main()

"""c_module.py"""
from b_module import B
class C(B):
    def __init__(self):
        super(C, self).__init__()
        self.result = None
    def run(self):
        self.result = self.a.execute()
        return self.result

"""b_module.py"""
from a_module import A
class B(object):
    def __init__(self):
        """
         Initialize and declare any members/methods that can be passed over class that inherit this class
        """
        self.a = A()
        self.name = Name()
    def run(self):
        pass

class Name:
    def __init__(self):
        self.test_dict = {}

"""a_module.py"""
class A(object):
    def __new__(cls):
        """
         Overriding the __new__ method to make the A a singleTon class
         :return: cls.instance
         """
        if not hasattr(cls, 'instance') or not cls.instance:
             cls.instance = super(A, cls).__new__(cls)
             return cls.instance
        def execute():
             print("class A")
             return "Coming from class A"

我还鼓励你更改模块命名。在处理这个问题时,很难不将模块与类混淆。如上所示,我已将模块名称更改为 snake-cased而保留类名称。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接