我想测试功能
is_myclass
。请帮助我了解如何编写成功的测试。
def is_myclass(obj):
"""This absurd stub is a simplified version of the production code."""
isinstance(obj, MyClass)
MyClass()
文档
Python文档用于unittest。mock演示了三种解决
isinstance
问题:
-
设置
spec
实数类的参数。
-
将实际类分配给
__class__
属性
-
使用
规格
在真实班级的补丁中。
__类别__
通常
__类别__
对象的属性将返回其类型。对于具有等级库的模拟对象,
__类别__
返回spec类。这允许模拟对象通过其替换/伪装为的对象的isinstance()测试:
>>> mock = Mock(spec=3)
>>> isinstance(mock, int)
True
__类别__
可分配给,这允许模拟通过
isinstance()
在不强制使用等级库的情况下进行检查:
>>> mock = Mock()
>>> mock.__class__ = dict
>>> isinstance(mock, dict)
True
[…]
如果您使用
规格
或
spec_set
和
patch()
正在替换类,则创建的模拟的返回值将具有相同的规范。
>>> Original = Class
>>> patcher = patch('__main__.Class', spec=True)
>>> MockClass = patcher.start()
>>> instance = MockClass()
>>> assert isinstance(instance, Original)
>>> patcher.stop()
测试
我已经编写了五个测试,每个测试都试图首先复制三个解决方案中的每一个,然后对目标代码进行实际测试。典型的模式是
assert isinstance
然后拨打
is\U myclass
。
所有测试均失败。
测试1
这是文档中提供的示例的副本,供使用
规格
信息技术
与文档的不同之处在于使用
spec=<class>
而不是
spec=<instance>
.它通过了
本地断言测试,但调用
is\U myclass
失败的原因是
MyClass
不会被嘲笑。
这相当于米歇尔·达米科对中类似问题的回答
isinstance and Mocking
。
测试2
这是测试1的修补等效物。这个
规格
参数无法设置
__类别__
而本地
断言isinstance
。
测试3
这是文档中提供的示例的副本,供使用
__类别__
.它通过了
本地断言测试,但调用
is\U myclass
失败的原因是
类名
不会被嘲笑。
测试4
这是测试3的修补等效物。分配给
__类别__
是否设置
__类别__
被嘲笑的人
类名
但这不会改变其类型,因此测试无法通过本地
断言isinstance
。
测试5
这是使用
规格
打电话给patch。它通过了本地断言测试,但仅通过访问MyClass的本地副本。因为此局部变量未在中使用
is\U myclass
呼叫失败。
密码
这段代码是作为一个独立的测试模块编写的,打算在PyCharm IDE中运行。您可能需要修改它以在其他测试环境中运行。
模块temp2。py公司
import unittest
import unittest.mock as mock
class WrongCodeTested(Exception):
pass
class MyClass:
def __init__(self):
"""This is a simplified version of a production class which must be mocked for unittesting."""
raise WrongCodeTested('Testing code in MyClass.__init__')
def is_myclass(obj):
"""This absurd stub is a simplified version of the production code."""
isinstance(obj, MyClass)
MyClass()
class ExamplesFromDocs(unittest.TestCase):
def test_1_spec(self):
obj = mock.Mock(spec=MyClass)
print(type(MyClass)) # <class 'type'>
assert isinstance(obj, MyClass) # Local assert test passes
is_myclass(obj) # Fail: MyClass instantiated
def test_2_spec_patch(self):
with mock.patch('temp2.MyClass', spec=True) as mock_myclass:
obj = mock_myclass()
print(type(mock_myclass)) # <class 'unittest.mock.MagicMock'>
print(type(MyClass)) # <class 'unittest.mock.MagicMock'>
assert isinstance(obj, MyClass) # Local assert test fails
def test_3__class__(self):
obj = mock.Mock()
obj.__class__ = MyClass
print(type(MyClass)) # <class 'type'>
isinstance(obj, MyClass) # Local assert test passes
is_myclass(obj) # Fail: MyClass instantiated
def test_4__class__patch(self):
Original = MyClass
with mock.patch('temp2.MyClass') as mock_myclass:
mock_myclass.__class__ = Original
obj = mock_myclass()
obj.__class__ = Original
print(MyClass.__class__) # <class 'temp2.MyClass'>
print(type(MyClass)) # <class 'unittest.mock.MagicMock'>
assert isinstance(obj, MyClass) # Local assert test fails
def test_5_patch_with_spec(self):
Original = MyClass
p = mock.patch('temp2.MyClass', spec=True)
MockMyClass = p.start()
obj = MockMyClass()
print(type(Original)) # <class 'type'>
print(type(MyClass)) # <class 'unittest.mock.MagicMock'>
print(type(MockMyClass)) # <class 'unittest.mock.MagicMock'>
assert isinstance(obj, Original) # Local assert test passes
is_myclass(obj) # Fail: Bad type for MyClass