无法模拟从另一个 class(creates/uses 单例对象)继承的 class
Unable to Mock class that inherits from another class (which creates/uses singleton object)
我有三个 classes 和一个单元测试用例:
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) test.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 时,出现以下错误:
错误: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 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 中使用的不同 return 值(通过修补)从 class C.py 中测试 运行()。
预先感谢您的帮助
编辑:即使我在 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)
我不得不将 B.py
中的导入更改为 import
而不是 from
。错误是因为 A
是从 B
模块中查找的,所以你的补丁必须是 @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"
我还鼓励您更改模块命名。在处理此问题时,很难不将模块与 类 混为一谈。你可以在上面看到我已经将模块名称更改为蛇形并保留 类 原样。
我有三个 classes 和一个单元测试用例: 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) test.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 时,出现以下错误:
错误: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 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 中使用的不同 return 值(通过修补)从 class C.py 中测试 运行()。 预先感谢您的帮助
编辑:即使我在 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)
我不得不将 B.py
中的导入更改为 import
而不是 from
。错误是因为 A
是从 B
模块中查找的,所以你的补丁必须是 @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"
我还鼓励您更改模块命名。在处理此问题时,很难不将模块与 类 混为一谈。你可以在上面看到我已经将模块名称更改为蛇形并保留 类 原样。